smbd: Simplify smbXsrv_open_clear_replay_cache()
[samba.git] / source3 / smbd / smb2_reply.c
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
8
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.
13
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.
18
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/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
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"
54 #include "source3/smbd/dir.h"
55
56 /****************************************************************************
57  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
58  path or anything including wildcards.
59  We're assuming here that '/' is not the second byte in any multibyte char
60  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
61  set.
62 ****************************************************************************/
63
64 /* Custom version for processing POSIX paths. */
65 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
66
67 NTSTATUS check_path_syntax(char *path, bool posix_path)
68 {
69         char *d = path;
70         const char *s = path;
71         NTSTATUS ret = NT_STATUS_OK;
72         bool start_of_name_component = True;
73         bool stream_started = false;
74         bool last_component_contains_wcard = false;
75
76         while (*s) {
77                 if (stream_started) {
78                         switch (*s) {
79                         case '/':
80                         case '\\':
81                                 return NT_STATUS_OBJECT_NAME_INVALID;
82                         case ':':
83                                 if (s[1] == '\0') {
84                                         return NT_STATUS_OBJECT_NAME_INVALID;
85                                 }
86                                 if (strchr_m(&s[1], ':')) {
87                                         return NT_STATUS_OBJECT_NAME_INVALID;
88                                 }
89                                 break;
90                         }
91                 }
92
93                 if ((*s == ':') && !posix_path && !stream_started) {
94                         if (last_component_contains_wcard) {
95                                 return NT_STATUS_OBJECT_NAME_INVALID;
96                         }
97                         /* Stream names allow more characters than file names.
98                            We're overloading posix_path here to allow a wider
99                            range of characters. If stream_started is true this
100                            is still a Windows path even if posix_path is true.
101                            JRA.
102                         */
103                         stream_started = true;
104                         start_of_name_component = false;
105                         posix_path = true;
106
107                         if (s[1] == '\0') {
108                                 return NT_STATUS_OBJECT_NAME_INVALID;
109                         }
110                 }
111
112                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
113                         /*
114                          * Safe to assume is not the second part of a mb char
115                          * as this is handled below.
116                          */
117                         /* Eat multiple '/' or '\\' */
118                         while (IS_PATH_SEP(*s,posix_path)) {
119                                 s++;
120                         }
121                         if ((d != path) && (*s != '\0')) {
122                                 /* We only care about non-leading or trailing '/' or '\\' */
123                                 *d++ = '/';
124                         }
125
126                         start_of_name_component = True;
127                         /* New component. */
128                         last_component_contains_wcard = false;
129                         continue;
130                 }
131
132                 if (start_of_name_component) {
133                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
134                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
135
136                                 /*
137                                  * No mb char starts with '.' so we're safe checking the directory separator here.
138                                  */
139
140                                 /* If  we just added a '/' - delete it */
141                                 if ((d > path) && (*(d-1) == '/')) {
142                                         *(d-1) = '\0';
143                                         d--;
144                                 }
145
146                                 /* Are we at the start ? Can't go back further if so. */
147                                 if (d <= path) {
148                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
149                                         break;
150                                 }
151                                 /* Go back one level... */
152                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
153                                 /* NOTE - if this assumption is invalid we are not in good shape... */
154                                 /* Decrement d first as d points to the *next* char to write into. */
155                                 for (d--; d > path; d--) {
156                                         if (*d == '/')
157                                                 break;
158                                 }
159                                 s += 2; /* Else go past the .. */
160                                 /* We're still at the start of a name component, just the previous one. */
161                                 continue;
162
163                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
164                                 if (posix_path) {
165                                         /* Eat the '.' */
166                                         s++;
167                                         continue;
168                                 }
169                         }
170
171                 }
172
173                 if (!(*s & 0x80)) {
174                         if (!posix_path) {
175                                 if (*s <= 0x1f || *s == '|') {
176                                         return NT_STATUS_OBJECT_NAME_INVALID;
177                                 }
178                                 switch (*s) {
179                                         case '*':
180                                         case '?':
181                                         case '<':
182                                         case '>':
183                                         case '"':
184                                                 last_component_contains_wcard = true;
185                                                 break;
186                                         default:
187                                                 break;
188                                 }
189                         }
190                         *d++ = *s++;
191                 } else {
192                         size_t ch_size;
193                         /* Get the size of the next MB character. */
194                         next_codepoint(s,&ch_size);
195                         switch(ch_size) {
196                                 case 5:
197                                         *d++ = *s++;
198                                         FALL_THROUGH;
199                                 case 4:
200                                         *d++ = *s++;
201                                         FALL_THROUGH;
202                                 case 3:
203                                         *d++ = *s++;
204                                         FALL_THROUGH;
205                                 case 2:
206                                         *d++ = *s++;
207                                         FALL_THROUGH;
208                                 case 1:
209                                         *d++ = *s++;
210                                         break;
211                                 default:
212                                         DBG_ERR("character length assumptions invalid !\n");
213                                         *d = '\0';
214                                         return NT_STATUS_INVALID_PARAMETER;
215                         }
216                 }
217                 start_of_name_component = False;
218         }
219
220         *d = '\0';
221
222         return ret;
223 }
224
225 /****************************************************************************
226  SMB2-only code to strip an MSDFS prefix from an incoming pathname.
227 ****************************************************************************/
228
229 NTSTATUS smb2_strip_dfs_path(const char *in_path, const char **out_path)
230 {
231         const char *path = in_path;
232
233         /* Match the Windows 2022 behavior for an empty DFS pathname. */
234         if (*path == '\0') {
235                 return NT_STATUS_INVALID_PARAMETER;
236         }
237         /* Strip any leading '\\' characters - MacOSX client behavior. */
238         while (*path == '\\') {
239                 path++;
240         }
241         /* We should now be pointing at the server name. Go past it. */
242         for (;;) {
243                 if (*path == '\0') {
244                         /* End of complete path. Exit OK. */
245                         goto out;
246                 }
247                 if (*path == '\\') {
248                         /* End of server name. Go past and break. */
249                         path++;
250                         break;
251                 }
252                 path++; /* Continue looking for end of server name or string. */
253         }
254
255         /* We should now be pointing at the share name. Go past it. */
256         for (;;) {
257                 if (*path == '\0') {
258                         /* End of complete path. Exit OK. */
259                         goto out;
260                 }
261                 if (*path == '\\') {
262                         /* End of share name. Go past and break. */
263                         path++;
264                         break;
265                 }
266                 if (*path == ':') {
267                         /* Only invalid character in sharename. */
268                         return NT_STATUS_OBJECT_NAME_INVALID;
269                 }
270                 path++; /* Continue looking for end of share name or string. */
271         }
272
273         /* path now points at the start of the real filename (if any). */
274
275   out:
276         /* We have stripped the DFS path prefix (if any). */
277         *out_path = path;
278         return NT_STATUS_OK;
279 }
280
281 /****************************************************************************
282  Pull a string and check the path allowing a wildcard - provide for error return.
283  Passes in posix flag.
284 ****************************************************************************/
285
286 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
287                         const char *base_ptr,
288                         uint16_t smb_flags2,
289                         char **pp_dest,
290                         const char *src,
291                         size_t src_len,
292                         int flags,
293                         bool posix_pathnames,
294                         NTSTATUS *err)
295 {
296         size_t ret;
297         char *dst = NULL;
298
299         *pp_dest = NULL;
300
301         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
302                                  src_len, flags);
303
304         if (!*pp_dest) {
305                 *err = NT_STATUS_INVALID_PARAMETER;
306                 return ret;
307         }
308
309         dst = *pp_dest;
310
311         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
312                 /*
313                  * A valid DFS path looks either like
314                  * /server/share
315                  * \server\share
316                  * (there may be more components after).
317                  * Either way it must have at least two separators.
318                  *
319                  * Ensure we end up as /server/share
320                  * so we don't need to special case
321                  * separator characters elsewhere in
322                  * the code.
323                  */
324                 char *server = NULL;
325                 char *share = NULL;
326                 char *remaining_path = NULL;
327                 char path_sep = 0;
328                 char *p = NULL;
329
330                 if (posix_pathnames && (dst[0] == '/')) {
331                         path_sep = dst[0];
332                 } else if (dst[0] == '\\') {
333                         path_sep = dst[0];
334                 }
335
336                 if (path_sep == 0) {
337                         goto local_path;
338                 }
339                 /*
340                  * May be a DFS path.
341                  * We need some heuristics here,
342                  * as clients differ on what constitutes
343                  * a well-formed DFS path. If the path
344                  * appears malformed, just fall back to
345                  * processing as a local path.
346                  */
347                 server = dst;
348
349                 /*
350                  * Cosmetic fix for Linux-only DFS clients.
351                  * The Linux kernel SMB1 client has a bug - it sends
352                  * DFS pathnames as:
353                  *
354                  * \\server\share\path
355                  *
356                  * Causing us to mis-parse server,share,remaining_path here
357                  * and jump into 'goto local_path' at 'share\path' instead
358                  * of 'path'.
359                  *
360                  * This doesn't cause an error as the limits on share names
361                  * are similar to those on pathnames.
362                  *
363                  * parse_dfs_path() which we call before filename parsing
364                  * copes with this by calling trim_char on the leading '\'
365                  * characters before processing.
366                  * Do the same here so logging of pathnames looks better.
367                  */
368                 if (server[1] == path_sep) {
369                         trim_char(&server[1], path_sep, '\0');
370                 }
371
372                 /*
373                  * Look to see if we also have /share following.
374                  */
375                 share = strchr(server+1, path_sep);
376                 if (share == NULL) {
377                         goto local_path;
378                 }
379                 /*
380                  * Ensure the server name does not contain
381                  * any possible path components by converting
382                  * them to _'s.
383                  */
384                 for (p = server + 1; p < share; p++) {
385                         if (*p == '/' || *p == '\\') {
386                                 *p = '_';
387                         }
388                 }
389                 /*
390                  * It's a well formed DFS path with
391                  * at least server and share components.
392                  * Replace the slashes with '/' and
393                  * pass the remainder to local_path.
394                  */
395                 *server = '/';
396                 *share = '/';
397                 /*
398                  * Skip past share so we don't pass the
399                  * sharename into check_path_syntax().
400                  */
401                 remaining_path = strchr(share+1, path_sep);
402                 if (remaining_path == NULL) {
403                         /*
404                          * Ensure the share name does not contain
405                          * any possible path components by converting
406                          * them to _'s.
407                          */
408                         for (p = share + 1; *p; p++) {
409                                 if (*p == '/' || *p == '\\') {
410                                         *p = '_';
411                                 }
412                         }
413                         /*
414                          * If no remaining path this was
415                          * a bare /server/share path. Just return.
416                          */
417                         *err = NT_STATUS_OK;
418                         return ret;
419                 }
420                 /*
421                  * Ensure the share name does not contain
422                  * any possible path components by converting
423                  * them to _'s.
424                  */
425                 for (p = share + 1; p < remaining_path; p++) {
426                         if (*p == '/' || *p == '\\') {
427                                 *p = '_';
428                         }
429                 }
430                 *remaining_path = '/';
431                 dst = remaining_path + 1;
432                 /* dst now points at any following components. */
433         }
434
435   local_path:
436
437         *err = check_path_syntax(dst, posix_pathnames);
438
439         return ret;
440 }
441
442 /****************************************************************************
443  Pull a string and check the path - provide for error return.
444 ****************************************************************************/
445
446 size_t srvstr_get_path(TALLOC_CTX *ctx,
447                         const char *base_ptr,
448                         uint16_t smb_flags2,
449                         char **pp_dest,
450                         const char *src,
451                         size_t src_len,
452                         int flags,
453                         NTSTATUS *err)
454 {
455         return srvstr_get_path_internal(ctx,
456                         base_ptr,
457                         smb_flags2,
458                         pp_dest,
459                         src,
460                         src_len,
461                         flags,
462                         false,
463                         err);
464 }
465
466 /****************************************************************************
467  Pull a string and check the path - provide for error return.
468  posix_pathnames version.
469 ****************************************************************************/
470
471 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
472                         const char *base_ptr,
473                         uint16_t smb_flags2,
474                         char **pp_dest,
475                         const char *src,
476                         size_t src_len,
477                         int flags,
478                         NTSTATUS *err)
479 {
480         return srvstr_get_path_internal(ctx,
481                         base_ptr,
482                         smb_flags2,
483                         pp_dest,
484                         src,
485                         src_len,
486                         flags,
487                         true,
488                         err);
489 }
490
491
492 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
493                                  char **pp_dest, const char *src, int flags,
494                                  NTSTATUS *err)
495 {
496         ssize_t bufrem = smbreq_bufrem(req, src);
497
498         if (bufrem == 0) {
499                 *err = NT_STATUS_INVALID_PARAMETER;
500                 return 0;
501         }
502
503         if (req->posix_pathnames) {
504                 return srvstr_get_path_internal(mem_ctx,
505                                 (const char *)req->inbuf,
506                                 req->flags2,
507                                 pp_dest,
508                                 src,
509                                 bufrem,
510                                 flags,
511                                 true,
512                                 err);
513         } else {
514                 return srvstr_get_path_internal(mem_ctx,
515                                 (const char *)req->inbuf,
516                                 req->flags2,
517                                 pp_dest,
518                                 src,
519                                 bufrem,
520                                 flags,
521                                 false,
522                                 err);
523         }
524 }
525
526 /**
527  * pull a string from the smb_buf part of a packet. In this case the
528  * string can either be null terminated or it can be terminated by the
529  * end of the smbbuf area
530  */
531 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
532                               char **dest, const uint8_t *src, int flags)
533 {
534         ssize_t bufrem = smbreq_bufrem(req, src);
535
536         if (bufrem == 0) {
537                 *dest = NULL;
538                 return 0;
539         }
540
541         return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
542                                   bufrem, flags);
543 }
544
545 /****************************************************************************
546  Check if we have a correct fsp pointing to a quota fake file. Replacement for
547  the CHECK_NTQUOTA_HANDLE_OK macro.
548 ****************************************************************************/
549
550 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
551                               files_struct *fsp)
552 {
553         if ((fsp == NULL) || (conn == NULL)) {
554                 return false;
555         }
556
557         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
558                 return false;
559         }
560
561         if (fsp->fsp_flags.is_directory) {
562                 return false;
563         }
564
565         if (fsp->fake_file_handle == NULL) {
566                 return false;
567         }
568
569         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
570                 return false;
571         }
572
573         if (fsp->fake_file_handle->private_data == NULL) {
574                 return false;
575         }
576
577         return true;
578 }
579
580 /****************************************************************************
581  Return the port number we've bound to on a socket.
582 ****************************************************************************/
583
584 static int get_socket_port(int fd)
585 {
586         struct samba_sockaddr saddr = {
587                 .sa_socklen = sizeof(struct sockaddr_storage),
588         };
589
590         if (fd == -1) {
591                 return -1;
592         }
593
594         if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
595                 int level = (errno == ENOTCONN) ? 2 : 0;
596                 DEBUG(level, ("getsockname failed. Error was %s\n",
597                                strerror(errno)));
598                 return -1;
599         }
600
601 #if defined(HAVE_IPV6)
602         if (saddr.u.sa.sa_family == AF_INET6) {
603                 return ntohs(saddr.u.in6.sin6_port);
604         }
605 #endif
606         if (saddr.u.sa.sa_family == AF_INET) {
607                 return ntohs(saddr.u.in.sin_port);
608         }
609         return -1;
610 }
611
612 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
613                                      const char *name, int name_type)
614 {
615         char *trim_name;
616         char *trim_name_type;
617         const char *retarget_parm;
618         char *retarget;
619         char *p;
620         int retarget_type = 0x20;
621         int retarget_port = NBT_SMB_PORT;
622         struct sockaddr_storage retarget_addr;
623         struct sockaddr_in *in_addr;
624         bool ret = false;
625         uint8_t outbuf[10];
626
627         if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
628                 return false;
629         }
630
631         trim_name = talloc_strdup(talloc_tos(), name);
632         if (trim_name == NULL) {
633                 goto fail;
634         }
635         trim_char(trim_name, ' ', ' ');
636
637         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
638                                          name_type);
639         if (trim_name_type == NULL) {
640                 goto fail;
641         }
642
643         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
644                                              trim_name_type, NULL);
645         if (retarget_parm == NULL) {
646                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
647                                                      trim_name, NULL);
648         }
649         if (retarget_parm == NULL) {
650                 goto fail;
651         }
652
653         retarget = talloc_strdup(trim_name, retarget_parm);
654         if (retarget == NULL) {
655                 goto fail;
656         }
657
658         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
659
660         p = strchr(retarget, ':');
661         if (p != NULL) {
662                 *p++ = '\0';
663                 retarget_port = atoi(p);
664         }
665
666         p = strchr_m(retarget, '#');
667         if (p != NULL) {
668                 *p++ = '\0';
669                 if (sscanf(p, "%x", &retarget_type) != 1) {
670                         goto fail;
671                 }
672         }
673
674         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
675         if (!ret) {
676                 DEBUG(10, ("could not resolve %s\n", retarget));
677                 goto fail;
678         }
679
680         if (retarget_addr.ss_family != AF_INET) {
681                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
682                 goto fail;
683         }
684
685         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
686
687         _smb_setlen(outbuf, 6);
688         SCVAL(outbuf, 0, 0x84);
689         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
690         *(uint16_t *)(outbuf+8) = htons(retarget_port);
691
692         if (!smb1_srv_send(xconn, (char *)outbuf, false, 0, false)) {
693                 exit_server_cleanly("netbios_session_retarget: smb1_srv_send "
694                                     "failed.");
695         }
696
697         ret = true;
698  fail:
699         TALLOC_FREE(trim_name);
700         return ret;
701 }
702
703 static void reply_called_name_not_present(char *outbuf)
704 {
705         smb_setlen(outbuf, 1);
706         SCVAL(outbuf, 0, 0x83);
707         SCVAL(outbuf, 4, 0x82);
708 }
709
710 /****************************************************************************
711  Reply to a (netbios-level) special message.
712 ****************************************************************************/
713
714 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
715 {
716         struct smbd_server_connection *sconn = xconn->client->sconn;
717         int msg_type = CVAL(inbuf,0);
718         int msg_flags = CVAL(inbuf,1);
719         /*
720          * We only really use 4 bytes of the outbuf, but for the smb_setlen
721          * calculation & friends (smb1_srv_send uses that) we need the full smb
722          * header.
723          */
724         char outbuf[smb_size];
725
726         memset(outbuf, '\0', sizeof(outbuf));
727
728         smb_setlen(outbuf,0);
729
730         switch (msg_type) {
731         case NBSSrequest: /* session request */
732         {
733                 /* inbuf_size is guaranteed to be at least 4. */
734                 fstring name1,name2;
735                 int name_type1, name_type2;
736                 int name_len1, name_len2;
737
738                 *name1 = *name2 = 0;
739
740                 if (xconn->transport.nbt.got_session) {
741                         exit_server_cleanly("multiple session request not permitted");
742                 }
743
744                 SCVAL(outbuf,0,NBSSpositive);
745                 SCVAL(outbuf,3,0);
746
747                 /* inbuf_size is guaranteed to be at least 4. */
748                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
749                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
750                         DEBUG(0,("Invalid name length in session request\n"));
751                         reply_called_name_not_present(outbuf);
752                         break;
753                 }
754                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
755                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
756                         DEBUG(0,("Invalid name length in session request\n"));
757                         reply_called_name_not_present(outbuf);
758                         break;
759                 }
760
761                 name_type1 = name_extract((unsigned char *)inbuf,
762                                 inbuf_size,(unsigned int)4,name1);
763                 name_type2 = name_extract((unsigned char *)inbuf,
764                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
765
766                 if (name_type1 == -1 || name_type2 == -1) {
767                         DEBUG(0,("Invalid name type in session request\n"));
768                         reply_called_name_not_present(outbuf);
769                         break;
770                 }
771
772                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
773                          name1, name_type1, name2, name_type2));
774
775                 if (netbios_session_retarget(xconn, name1, name_type1)) {
776                         exit_server_cleanly("retargeted client");
777                 }
778
779                 /*
780                  * Windows NT/2k uses "*SMBSERVER" and XP uses
781                  * "*SMBSERV" arrggg!!!
782                  */
783                 if (strequal(name1, "*SMBSERVER     ")
784                     || strequal(name1, "*SMBSERV       "))  {
785                         char *raddr;
786
787                         raddr = tsocket_address_inet_addr_string(sconn->remote_address,
788                                                                  talloc_tos());
789                         if (raddr == NULL) {
790                                 exit_server_cleanly("could not allocate raddr");
791                         }
792
793                         fstrcpy(name1, raddr);
794                 }
795
796                 set_local_machine_name(name1, True);
797                 set_remote_machine_name(name2, True);
798
799                 if (is_ipaddress(sconn->remote_hostname)) {
800                         char *p = discard_const_p(char, sconn->remote_hostname);
801
802                         talloc_free(p);
803
804                         sconn->remote_hostname = talloc_strdup(sconn,
805                                                 get_remote_machine_name());
806                         if (sconn->remote_hostname == NULL) {
807                                 exit_server_cleanly("could not copy remote name");
808                         }
809                         xconn->remote_hostname = sconn->remote_hostname;
810                 }
811
812                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
813                          get_local_machine_name(), get_remote_machine_name(),
814                          name_type2));
815
816                 if (name_type2 == 'R') {
817                         /* We are being asked for a pathworks session ---
818                            no thanks! */
819                         reply_called_name_not_present(outbuf);
820                         break;
821                 }
822
823                 reload_services(sconn, conn_snum_used, true);
824                 reopen_logs();
825
826                 xconn->transport.nbt.got_session = true;
827                 break;
828         }
829
830         case 0x89: /* session keepalive request
831                       (some old clients produce this?) */
832                 SCVAL(outbuf,0,NBSSkeepalive);
833                 SCVAL(outbuf,3,0);
834                 break;
835
836         case NBSSpositive: /* positive session response */
837         case NBSSnegative: /* negative session response */
838         case NBSSretarget: /* retarget session response */
839                 DEBUG(0,("Unexpected session response\n"));
840                 break;
841
842         case NBSSkeepalive: /* session keepalive */
843         default:
844                 return;
845         }
846
847         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
848                     msg_type, msg_flags));
849
850         if (!smb1_srv_send(xconn, outbuf, false, 0, false)) {
851                 exit_server_cleanly("reply_special: smb1_srv_send failed.");
852         }
853
854         if (CVAL(outbuf, 0) != 0x82) {
855                 exit_server_cleanly("invalid netbios session");
856         }
857         return;
858 }
859
860 /*******************************************************************
861  * unlink a file with all relevant access checks
862  *******************************************************************/
863
864 NTSTATUS unlink_internals(connection_struct *conn,
865                         struct smb_request *req,
866                         uint32_t dirtype,
867                         struct files_struct *dirfsp,
868                         struct smb_filename *smb_fname)
869 {
870         uint32_t fattr;
871         files_struct *fsp;
872         uint32_t dirtype_orig = dirtype;
873         NTSTATUS status;
874         int ret;
875         struct smb2_create_blobs *posx = NULL;
876
877         if (dirtype == 0) {
878                 dirtype = FILE_ATTRIBUTE_NORMAL;
879         }
880
881         DBG_DEBUG("%s, dirtype = %d\n",
882                   smb_fname_str_dbg(smb_fname),
883                   dirtype);
884
885         if (!CAN_WRITE(conn)) {
886                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
887         }
888
889         ret = vfs_stat(conn, smb_fname);
890         if (ret != 0) {
891                 return map_nt_error_from_unix(errno);
892         }
893
894         fattr = fdos_mode(smb_fname->fsp);
895
896         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
897                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
898         }
899
900         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
901         if (!dirtype) {
902                 return NT_STATUS_NO_SUCH_FILE;
903         }
904
905         if (!dir_check_ftype(fattr, dirtype)) {
906                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
907                         return NT_STATUS_FILE_IS_A_DIRECTORY;
908                 }
909                 return NT_STATUS_NO_SUCH_FILE;
910         }
911
912         if (dirtype_orig & 0x8000) {
913                 /* These will never be set for POSIX. */
914                 return NT_STATUS_NO_SUCH_FILE;
915         }
916
917 #if 0
918         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
919                 return NT_STATUS_FILE_IS_A_DIRECTORY;
920         }
921
922         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
923                 return NT_STATUS_NO_SUCH_FILE;
924         }
925
926         if (dirtype & 0xFF00) {
927                 /* These will never be set for POSIX. */
928                 return NT_STATUS_NO_SUCH_FILE;
929         }
930
931         dirtype &= 0xFF;
932         if (!dirtype) {
933                 return NT_STATUS_NO_SUCH_FILE;
934         }
935
936         /* Can't delete a directory. */
937         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
938                 return NT_STATUS_FILE_IS_A_DIRECTORY;
939         }
940 #endif
941
942 #if 0 /* JRATEST */
943         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
944                 return NT_STATUS_OBJECT_NAME_INVALID;
945 #endif /* JRATEST */
946
947         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
948                 status = make_smb2_posix_create_ctx(
949                         talloc_tos(), &posx, 0777);
950                 if (!NT_STATUS_IS_OK(status)) {
951                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
952                                     nt_errstr(status));
953                         return status;
954                 }
955         }
956
957         /* On open checks the open itself will check the share mode, so
958            don't do it here as we'll get it wrong. */
959
960         status = SMB_VFS_CREATE_FILE
961                 (conn,                  /* conn */
962                  req,                   /* req */
963                  dirfsp,                        /* dirfsp */
964                  smb_fname,             /* fname */
965                  DELETE_ACCESS,         /* access_mask */
966                  FILE_SHARE_NONE,       /* share_access */
967                  FILE_OPEN,             /* create_disposition*/
968                  FILE_NON_DIRECTORY_FILE |
969                         FILE_OPEN_REPARSE_POINT, /* create_options */
970                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
971                  0,                     /* oplock_request */
972                  NULL,                  /* lease */
973                  0,                     /* allocation_size */
974                  0,                     /* private_flags */
975                  NULL,                  /* sd */
976                  NULL,                  /* ea_list */
977                  &fsp,                  /* result */
978                  NULL,                  /* pinfo */
979                  posx,                  /* in_context_blobs */
980                  NULL);                 /* out_context_blobs */
981
982         TALLOC_FREE(posx);
983
984         if (!NT_STATUS_IS_OK(status)) {
985                 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
986                            nt_errstr(status));
987                 return status;
988         }
989
990         status = can_set_delete_on_close(fsp, fattr);
991         if (!NT_STATUS_IS_OK(status)) {
992                 DBG_DEBUG("can_set_delete_on_close for file %s - "
993                         "(%s)\n",
994                         smb_fname_str_dbg(smb_fname),
995                         nt_errstr(status));
996                 close_file_free(req, &fsp, NORMAL_CLOSE);
997                 return status;
998         }
999
1000         /* The set is across all open files on this dev/inode pair. */
1001         if (!set_delete_on_close(fsp, True,
1002                                 conn->session_info->security_token,
1003                                 conn->session_info->unix_token)) {
1004                 close_file_free(req, &fsp, NORMAL_CLOSE);
1005                 return NT_STATUS_ACCESS_DENIED;
1006         }
1007
1008         return close_file_free(req, &fsp, NORMAL_CLOSE);
1009 }
1010
1011 /****************************************************************************
1012  Fake (read/write) sendfile. Returns -1 on read or write fail.
1013 ****************************************************************************/
1014
1015 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
1016                       off_t startpos, size_t nread)
1017 {
1018         size_t bufsize;
1019         size_t tosend = nread;
1020         char *buf;
1021
1022         if (nread == 0) {
1023                 return 0;
1024         }
1025
1026         bufsize = MIN(nread, 65536);
1027
1028         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
1029                 return -1;
1030         }
1031
1032         while (tosend > 0) {
1033                 ssize_t ret;
1034                 size_t cur_read;
1035
1036                 cur_read = MIN(tosend, bufsize);
1037                 ret = read_file(fsp,buf,startpos,cur_read);
1038                 if (ret == -1) {
1039                         SAFE_FREE(buf);
1040                         return -1;
1041                 }
1042
1043                 /* If we had a short read, fill with zeros. */
1044                 if (ret < cur_read) {
1045                         memset(buf + ret, '\0', cur_read - ret);
1046                 }
1047
1048                 ret = write_data(xconn->transport.sock, buf, cur_read);
1049                 if (ret != cur_read) {
1050                         int saved_errno = errno;
1051                         /*
1052                          * Try and give an error message saying what
1053                          * client failed.
1054                          */
1055                         DEBUG(0, ("write_data failed for client %s. "
1056                                   "Error %s\n",
1057                                   smbXsrv_connection_dbg(xconn),
1058                                   strerror(saved_errno)));
1059                         SAFE_FREE(buf);
1060                         errno = saved_errno;
1061                         return -1;
1062                 }
1063                 tosend -= cur_read;
1064                 startpos += cur_read;
1065         }
1066
1067         SAFE_FREE(buf);
1068         return (ssize_t)nread;
1069 }
1070
1071 /****************************************************************************
1072  Deal with the case of sendfile reading less bytes from the file than
1073  requested. Fill with zeros (all we can do). Returns 0 on success
1074 ****************************************************************************/
1075
1076 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
1077                             files_struct *fsp,
1078                             ssize_t nread,
1079                             size_t headersize,
1080                             size_t smb_maxcnt)
1081 {
1082 #define SHORT_SEND_BUFSIZE 1024
1083         if (nread < headersize) {
1084                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
1085                         "header for file %s (%s). Terminating\n",
1086                         fsp_str_dbg(fsp), strerror(errno)));
1087                 return -1;
1088         }
1089
1090         nread -= headersize;
1091
1092         if (nread < smb_maxcnt) {
1093                 char buf[SHORT_SEND_BUFSIZE] = { 0 };
1094
1095                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
1096                         "with zeros !\n", fsp_str_dbg(fsp)));
1097
1098                 while (nread < smb_maxcnt) {
1099                         /*
1100                          * We asked for the real file size and told sendfile
1101                          * to not go beyond the end of the file. But it can
1102                          * happen that in between our fstat call and the
1103                          * sendfile call the file was truncated. This is very
1104                          * bad because we have already announced the larger
1105                          * number of bytes to the client.
1106                          *
1107                          * The best we can do now is to send 0-bytes, just as
1108                          * a read from a hole in a sparse file would do.
1109                          *
1110                          * This should happen rarely enough that I don't care
1111                          * about efficiency here :-)
1112                          */
1113                         size_t to_write;
1114                         ssize_t ret;
1115
1116                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
1117                         ret = write_data(xconn->transport.sock, buf, to_write);
1118                         if (ret != to_write) {
1119                                 int saved_errno = errno;
1120                                 /*
1121                                  * Try and give an error message saying what
1122                                  * client failed.
1123                                  */
1124                                 DEBUG(0, ("write_data failed for client %s. "
1125                                           "Error %s\n",
1126                                           smbXsrv_connection_dbg(xconn),
1127                                           strerror(saved_errno)));
1128                                 errno = saved_errno;
1129                                 return -1;
1130                         }
1131                         nread += to_write;
1132                 }
1133         }
1134
1135         return 0;
1136 }
1137
1138 /*******************************************************************
1139  Check if a user is allowed to rename a file.
1140 ********************************************************************/
1141
1142 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1143                         uint16_t dirtype)
1144 {
1145         NTSTATUS status;
1146
1147         if (fsp->fsp_name->twrp != 0) {
1148                 /* Get the error right, this is what Windows returns. */
1149                 return NT_STATUS_NOT_SAME_DEVICE;
1150         }
1151
1152         if (!CAN_WRITE(conn)) {
1153                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1154         }
1155
1156         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
1157                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1158                 /* Only bother to read the DOS attribute if we might deny the
1159                    rename on the grounds of attribute mismatch. */
1160                 uint32_t fmode = fdos_mode(fsp);
1161                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1162                         return NT_STATUS_NO_SUCH_FILE;
1163                 }
1164         }
1165
1166         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1167                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
1168                         return NT_STATUS_OK;
1169                 }
1170
1171                 /* If no pathnames are open below this
1172                    directory, allow the rename. */
1173
1174                 if (lp_strict_rename(SNUM(conn))) {
1175                         /*
1176                          * Strict rename, check open file db.
1177                          */
1178                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
1179                                 return NT_STATUS_ACCESS_DENIED;
1180                         }
1181                 } else if (file_find_subpath(fsp)) {
1182                         /*
1183                          * No strict rename, just look in local process.
1184                          */
1185                         return NT_STATUS_ACCESS_DENIED;
1186                 }
1187                 return NT_STATUS_OK;
1188         }
1189
1190         status = check_any_access_fsp(fsp, DELETE_ACCESS | FILE_WRITE_ATTRIBUTES);
1191         if (!NT_STATUS_IS_OK(status)) {
1192                 return status;
1193         }
1194         return NT_STATUS_OK;
1195 }
1196
1197 /****************************************************************************
1198  Ensure open files have their names updated. Updated to notify other smbd's
1199  asynchronously.
1200 ****************************************************************************/
1201
1202 static void rename_open_files(connection_struct *conn,
1203                               struct share_mode_lock *lck,
1204                               struct file_id id,
1205                               uint32_t orig_name_hash,
1206                               const struct smb_filename *smb_fname_dst)
1207 {
1208         files_struct *fsp;
1209         bool did_rename = False;
1210         NTSTATUS status;
1211         uint32_t new_name_hash = 0;
1212
1213         for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
1214             fsp = file_find_di_next(fsp, false)) {
1215                 SMB_STRUCT_STAT fsp_orig_sbuf;
1216                 struct file_id_buf idbuf;
1217                 /* fsp_name is a relative path under the fsp. To change this for other
1218                    sharepaths we need to manipulate relative paths. */
1219                 /* TODO - create the absolute path and manipulate the newname
1220                    relative to the sharepath. */
1221                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
1222                         continue;
1223                 }
1224                 if (fsp->name_hash != orig_name_hash) {
1225                         continue;
1226                 }
1227                 DBG_DEBUG("renaming file %s "
1228                           "(file_id %s) from %s -> %s\n",
1229                           fsp_fnum_dbg(fsp),
1230                           file_id_str_buf(fsp->file_id, &idbuf),
1231                           fsp_str_dbg(fsp),
1232                           smb_fname_str_dbg(smb_fname_dst));
1233
1234                 /*
1235                  * The incoming smb_fname_dst here has an
1236                  * invalid stat struct (it must not have
1237                  * existed for the rename to succeed).
1238                  * Preserve the existing stat from the
1239                  * open fsp after fsp_set_smb_fname()
1240                  * overwrites with the invalid stat.
1241                  *
1242                  * We will do an fstat before returning
1243                  * any of this metadata to the client anyway.
1244                  */
1245                 fsp_orig_sbuf = fsp->fsp_name->st;
1246                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
1247                 if (NT_STATUS_IS_OK(status)) {
1248                         did_rename = True;
1249                         new_name_hash = fsp->name_hash;
1250                         /* Restore existing stat. */
1251                         fsp->fsp_name->st = fsp_orig_sbuf;
1252                 }
1253         }
1254
1255         if (!did_rename) {
1256                 struct file_id_buf idbuf;
1257                 DBG_DEBUG("no open files on file_id %s "
1258                           "for %s\n",
1259                           file_id_str_buf(id, &idbuf),
1260                           smb_fname_str_dbg(smb_fname_dst));
1261         }
1262
1263         /* Send messages to all smbd's (not ourself) that the name has changed. */
1264         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
1265                               orig_name_hash, new_name_hash,
1266                               smb_fname_dst);
1267
1268 }
1269
1270 /****************************************************************************
1271  We need to check if the source path is a parent directory of the destination
1272  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
1273  refuse the rename with a sharing violation. Under UNIX the above call can
1274  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
1275  probably need to check that the client is a Windows one before disallowing
1276  this as a UNIX client (one with UNIX extensions) can know the source is a
1277  symlink and make this decision intelligently. Found by an excellent bug
1278  report from <AndyLiebman@aol.com>.
1279 ****************************************************************************/
1280
1281 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
1282                                      const struct smb_filename *smb_fname_dst)
1283 {
1284         const char *psrc = smb_fname_src->base_name;
1285         const char *pdst = smb_fname_dst->base_name;
1286         size_t slen;
1287
1288         if (psrc[0] == '.' && psrc[1] == '/') {
1289                 psrc += 2;
1290         }
1291         if (pdst[0] == '.' && pdst[1] == '/') {
1292                 pdst += 2;
1293         }
1294         if ((slen = strlen(psrc)) > strlen(pdst)) {
1295                 return False;
1296         }
1297         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
1298 }
1299
1300 /*
1301  * Do the notify calls from a rename
1302  */
1303
1304 static void notify_rename(connection_struct *conn, bool is_dir,
1305                           const struct smb_filename *smb_fname_src,
1306                           const struct smb_filename *smb_fname_dst)
1307 {
1308         char *parent_dir_src = NULL;
1309         char *parent_dir_dst = NULL;
1310         uint32_t mask;
1311
1312         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
1313                 : FILE_NOTIFY_CHANGE_FILE_NAME;
1314
1315         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
1316                             &parent_dir_src, NULL) ||
1317             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
1318                             &parent_dir_dst, NULL)) {
1319                 goto out;
1320         }
1321
1322         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
1323                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
1324                              smb_fname_src->base_name);
1325                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
1326                              smb_fname_dst->base_name);
1327         }
1328         else {
1329                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
1330                              smb_fname_src->base_name);
1331                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
1332                              smb_fname_dst->base_name);
1333         }
1334
1335         /* this is a strange one. w2k3 gives an additional event for
1336            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
1337            files, but not directories */
1338         if (!is_dir) {
1339                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
1340                              FILE_NOTIFY_CHANGE_ATTRIBUTES
1341                              |FILE_NOTIFY_CHANGE_CREATION,
1342                              smb_fname_dst->base_name);
1343         }
1344  out:
1345         TALLOC_FREE(parent_dir_src);
1346         TALLOC_FREE(parent_dir_dst);
1347 }
1348
1349 /****************************************************************************
1350  Returns an error if the parent directory for a filename is open in an
1351  incompatible way.
1352 ****************************************************************************/
1353
1354 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
1355                                         const struct smb_filename *smb_fname_dst_in)
1356 {
1357         struct smb_filename *smb_fname_parent = NULL;
1358         struct file_id id;
1359         files_struct *fsp = NULL;
1360         int ret;
1361         NTSTATUS status;
1362
1363         status = SMB_VFS_PARENT_PATHNAME(conn,
1364                                          talloc_tos(),
1365                                          smb_fname_dst_in,
1366                                          &smb_fname_parent,
1367                                          NULL);
1368         if (!NT_STATUS_IS_OK(status)) {
1369                 return status;
1370         }
1371
1372         ret = vfs_stat(conn, smb_fname_parent);
1373         if (ret == -1) {
1374                 return map_nt_error_from_unix(errno);
1375         }
1376
1377         /*
1378          * We're only checking on this smbd here, mostly good
1379          * enough.. and will pass tests.
1380          */
1381
1382         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
1383         for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
1384                         fsp = file_find_di_next(fsp, true)) {
1385                 if (fsp->access_mask & DELETE_ACCESS) {
1386                         return NT_STATUS_SHARING_VIOLATION;
1387                 }
1388         }
1389         return NT_STATUS_OK;
1390 }
1391
1392 /****************************************************************************
1393  Rename an open file - given an fsp.
1394 ****************************************************************************/
1395
1396 NTSTATUS rename_internals_fsp(connection_struct *conn,
1397                         files_struct *fsp,
1398                         struct smb_filename *smb_fname_dst_in,
1399                         const char *dst_original_lcomp,
1400                         uint32_t attrs,
1401                         bool replace_if_exists)
1402 {
1403         TALLOC_CTX *ctx = talloc_tos();
1404         struct smb_filename *parent_dir_fname_dst = NULL;
1405         struct smb_filename *parent_dir_fname_dst_atname = NULL;
1406         struct smb_filename *parent_dir_fname_src = NULL;
1407         struct smb_filename *parent_dir_fname_src_atname = NULL;
1408         struct smb_filename *smb_fname_dst = NULL;
1409         NTSTATUS status = NT_STATUS_OK;
1410         struct share_mode_lock *lck = NULL;
1411         uint32_t access_mask = SEC_DIR_ADD_FILE;
1412         bool dst_exists, old_is_stream, new_is_stream;
1413         int ret;
1414         bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1415                                 true : conn->case_sensitive;
1416         bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1417                                 true : conn->case_preserve;
1418
1419         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
1420         if (!NT_STATUS_IS_OK(status)) {
1421                 return status;
1422         }
1423
1424         if (file_has_open_streams(fsp)) {
1425                 return NT_STATUS_ACCESS_DENIED;
1426         }
1427
1428         /* Make a copy of the dst smb_fname structs */
1429
1430         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
1431         if (smb_fname_dst == NULL) {
1432                 status = NT_STATUS_NO_MEMORY;
1433                 goto out;
1434         }
1435
1436         /*
1437          * Check for special case with case preserving and not
1438          * case sensitive. If the new last component differs from the original
1439          * last component only by case, then we should allow
1440          * the rename (user is trying to change the case of the
1441          * filename).
1442          */
1443         if (!case_sensitive && case_preserve &&
1444             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1445             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
1446                 char *fname_dst_parent = NULL;
1447                 const char *fname_dst_lcomp = NULL;
1448                 char *orig_lcomp_path = NULL;
1449                 char *orig_lcomp_stream = NULL;
1450                 bool ok = true;
1451
1452                 /*
1453                  * Split off the last component of the processed
1454                  * destination name. We will compare this to
1455                  * the split components of dst_original_lcomp.
1456                  */
1457                 if (!parent_dirname(ctx,
1458                                 smb_fname_dst->base_name,
1459                                 &fname_dst_parent,
1460                                 &fname_dst_lcomp)) {
1461                         status = NT_STATUS_NO_MEMORY;
1462                         goto out;
1463                 }
1464
1465                 /*
1466                  * The dst_original_lcomp component contains
1467                  * the last_component of the path + stream
1468                  * name (if a stream exists).
1469                  *
1470                  * Split off the stream name so we
1471                  * can check them separately.
1472                  */
1473
1474                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
1475                         /* POSIX - no stream component. */
1476                         orig_lcomp_path = talloc_strdup(ctx,
1477                                                 dst_original_lcomp);
1478                         if (orig_lcomp_path == NULL) {
1479                                 ok = false;
1480                         }
1481                 } else {
1482                         ok = split_stream_filename(ctx,
1483                                         dst_original_lcomp,
1484                                         &orig_lcomp_path,
1485                                         &orig_lcomp_stream);
1486                 }
1487
1488                 if (!ok) {
1489                         TALLOC_FREE(fname_dst_parent);
1490                         status = NT_STATUS_NO_MEMORY;
1491                         goto out;
1492                 }
1493
1494                 /* If the base names only differ by case, use original. */
1495                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
1496                         char *tmp;
1497                         /*
1498                          * Replace the modified last component with the
1499                          * original.
1500                          */
1501                         if (!ISDOT(fname_dst_parent)) {
1502                                 tmp = talloc_asprintf(smb_fname_dst,
1503                                         "%s/%s",
1504                                         fname_dst_parent,
1505                                         orig_lcomp_path);
1506                         } else {
1507                                 tmp = talloc_strdup(smb_fname_dst,
1508                                         orig_lcomp_path);
1509                         }
1510                         if (tmp == NULL) {
1511                                 status = NT_STATUS_NO_MEMORY;
1512                                 TALLOC_FREE(fname_dst_parent);
1513                                 TALLOC_FREE(orig_lcomp_path);
1514                                 TALLOC_FREE(orig_lcomp_stream);
1515                                 goto out;
1516                         }
1517                         TALLOC_FREE(smb_fname_dst->base_name);
1518                         smb_fname_dst->base_name = tmp;
1519                 }
1520
1521                 /* If the stream_names only differ by case, use original. */
1522                 if(!strcsequal(smb_fname_dst->stream_name,
1523                                orig_lcomp_stream)) {
1524                         /* Use the original stream. */
1525                         char *tmp = talloc_strdup(smb_fname_dst,
1526                                             orig_lcomp_stream);
1527                         if (tmp == NULL) {
1528                                 status = NT_STATUS_NO_MEMORY;
1529                                 TALLOC_FREE(fname_dst_parent);
1530                                 TALLOC_FREE(orig_lcomp_path);
1531                                 TALLOC_FREE(orig_lcomp_stream);
1532                                 goto out;
1533                         }
1534                         TALLOC_FREE(smb_fname_dst->stream_name);
1535                         smb_fname_dst->stream_name = tmp;
1536                 }
1537                 TALLOC_FREE(fname_dst_parent);
1538                 TALLOC_FREE(orig_lcomp_path);
1539                 TALLOC_FREE(orig_lcomp_stream);
1540         }
1541
1542         /*
1543          * If the src and dest names are identical - including case,
1544          * don't do the rename, just return success.
1545          */
1546
1547         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1548             strcsequal(fsp->fsp_name->stream_name,
1549                        smb_fname_dst->stream_name)) {
1550                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
1551                           "- returning success\n",
1552                           smb_fname_str_dbg(smb_fname_dst)));
1553                 status = NT_STATUS_OK;
1554                 goto out;
1555         }
1556
1557         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
1558         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
1559
1560         /* Return the correct error code if both names aren't streams. */
1561         if (!old_is_stream && new_is_stream) {
1562                 status = NT_STATUS_OBJECT_NAME_INVALID;
1563                 goto out;
1564         }
1565
1566         if (old_is_stream && !new_is_stream) {
1567                 status = NT_STATUS_INVALID_PARAMETER;
1568                 goto out;
1569         }
1570
1571         dst_exists = vfs_stat(conn, smb_fname_dst) == 0;
1572
1573         if(!replace_if_exists && dst_exists) {
1574                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
1575                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1576                           smb_fname_str_dbg(smb_fname_dst)));
1577                 status = NT_STATUS_OBJECT_NAME_COLLISION;
1578                 goto out;
1579         }
1580
1581         /*
1582          * Drop the pathref fsp on the destination otherwise we trip upon in in
1583          * the below check for open files check.
1584          */
1585         if (smb_fname_dst_in->fsp != NULL) {
1586                 fd_close(smb_fname_dst_in->fsp);
1587                 file_free(NULL, smb_fname_dst_in->fsp);
1588                 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
1589         }
1590
1591         if (dst_exists) {
1592                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
1593                     &smb_fname_dst->st);
1594                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
1595                                                            fileid, true);
1596                 /* The file can be open when renaming a stream */
1597                 if (dst_fsp && !new_is_stream) {
1598                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
1599                         status = NT_STATUS_ACCESS_DENIED;
1600                         goto out;
1601                 }
1602         }
1603
1604         /* Ensure we have a valid stat struct for the source. */
1605         status = vfs_stat_fsp(fsp);
1606         if (!NT_STATUS_IS_OK(status)) {
1607                 goto out;
1608         }
1609
1610         status = can_rename(conn, fsp, attrs);
1611
1612         if (!NT_STATUS_IS_OK(status)) {
1613                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1614                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1615                           smb_fname_str_dbg(smb_fname_dst)));
1616                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
1617                         status = NT_STATUS_ACCESS_DENIED;
1618                 goto out;
1619         }
1620
1621         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
1622                 status = NT_STATUS_ACCESS_DENIED;
1623                 goto out;
1624         }
1625
1626         /* Do we have rights to move into the destination ? */
1627         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1628                 /* We're moving a directory. */
1629                 access_mask = SEC_DIR_ADD_SUBDIR;
1630         }
1631
1632         /*
1633          * Get a pathref on the destination parent directory, so
1634          * we can call check_parent_access_fsp().
1635          */
1636         status = parent_pathref(ctx,
1637                                 conn->cwd_fsp,
1638                                 smb_fname_dst,
1639                                 &parent_dir_fname_dst,
1640                                 &parent_dir_fname_dst_atname);
1641         if (!NT_STATUS_IS_OK(status)) {
1642                 goto out;
1643         }
1644
1645         status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
1646                                 access_mask);
1647         if (!NT_STATUS_IS_OK(status)) {
1648                 DBG_INFO("check_parent_access_fsp on "
1649                         "dst %s returned %s\n",
1650                         smb_fname_str_dbg(smb_fname_dst),
1651                         nt_errstr(status));
1652                 goto out;
1653         }
1654
1655         /*
1656          * If the target existed, make sure the destination
1657          * atname has the same stat struct.
1658          */
1659         parent_dir_fname_dst_atname->st = smb_fname_dst->st;
1660
1661         /*
1662          * It's very common that source and
1663          * destination directories are the same.
1664          * Optimize by not opening the
1665          * second parent_pathref if we know
1666          * this is the case.
1667          */
1668
1669         status = SMB_VFS_PARENT_PATHNAME(conn,
1670                                          ctx,
1671                                          fsp->fsp_name,
1672                                          &parent_dir_fname_src,
1673                                          &parent_dir_fname_src_atname);
1674         if (!NT_STATUS_IS_OK(status)) {
1675                 goto out;
1676         }
1677
1678         /*
1679          * We do a case-sensitive string comparison. We want to be *sure*
1680          * this is the same path. The worst that can happen if
1681          * the case doesn't match is we lose out on the optimization,
1682          * the code still works.
1683          *
1684          * We can ignore twrp fields here. Rename is not allowed on
1685          * shadow copy handles.
1686          */
1687
1688         if (strcmp(parent_dir_fname_src->base_name,
1689                    parent_dir_fname_dst->base_name) == 0) {
1690                 /*
1691                  * parent directory is the same for source
1692                  * and destination.
1693                  */
1694                 /* Reparent the src_atname to the parent_dir_dest fname. */
1695                 parent_dir_fname_src_atname = talloc_move(
1696                                                 parent_dir_fname_dst,
1697                                                 &parent_dir_fname_src_atname);
1698                 /* Free the unneeded duplicate parent name. */
1699                 TALLOC_FREE(parent_dir_fname_src);
1700                 /*
1701                  * And make the source parent name a copy of the
1702                  * destination parent name.
1703                  */
1704                 parent_dir_fname_src = parent_dir_fname_dst;
1705
1706                 /*
1707                  * Ensure we have a pathref fsp on the
1708                  * parent_dir_fname_src_atname to match the code in the else
1709                  * branch where we use parent_pathref().
1710                  */
1711                 status = reference_smb_fname_fsp_link(
1712                         parent_dir_fname_src_atname,
1713                         fsp->fsp_name);
1714                 if (!NT_STATUS_IS_OK(status)) {
1715                         goto out;
1716                 }
1717         } else {
1718                 /*
1719                  * source and destination parent directories are
1720                  * different.
1721                  *
1722                  * Get a pathref on the source parent directory, so
1723                  * we can do a relative rename.
1724                  */
1725                 TALLOC_FREE(parent_dir_fname_src);
1726                 status = parent_pathref(ctx,
1727                                 conn->cwd_fsp,
1728                                 fsp->fsp_name,
1729                                 &parent_dir_fname_src,
1730                                 &parent_dir_fname_src_atname);
1731                 if (!NT_STATUS_IS_OK(status)) {
1732                         goto out;
1733                 }
1734         }
1735
1736         /*
1737          * Some modules depend on the source smb_fname having a valid stat.
1738          * The parent_dir_fname_src_atname is the relative name of the
1739          * currently open file, so just copy the stat from the open fsp.
1740          */
1741         parent_dir_fname_src_atname->st = fsp->fsp_name->st;
1742
1743         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1744
1745         /*
1746          * We have the file open ourselves, so not being able to get the
1747          * corresponding share mode lock is a fatal error.
1748          */
1749
1750         SMB_ASSERT(lck != NULL);
1751
1752         ret = SMB_VFS_RENAMEAT(conn,
1753                         parent_dir_fname_src->fsp,
1754                         parent_dir_fname_src_atname,
1755                         parent_dir_fname_dst->fsp,
1756                         parent_dir_fname_dst_atname);
1757         if (ret == 0) {
1758                 uint32_t create_options = fh_get_private_options(fsp->fh);
1759
1760                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
1761                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1762                           smb_fname_str_dbg(smb_fname_dst)));
1763
1764                 notify_rename(conn,
1765                               fsp->fsp_flags.is_directory,
1766                               fsp->fsp_name,
1767                               smb_fname_dst);
1768
1769                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
1770                                   smb_fname_dst);
1771
1772                 if (!fsp->fsp_flags.is_directory &&
1773                     (lp_map_archive(SNUM(conn)) ||
1774                      lp_store_dos_attributes(SNUM(conn))))
1775                 {
1776                         /*
1777                          * We must set the archive bit on the newly renamed
1778                          * file.
1779                          */
1780                         status = vfs_stat_fsp(fsp);
1781                         if (NT_STATUS_IS_OK(status)) {
1782                                 uint32_t old_dosmode;
1783                                 old_dosmode = fdos_mode(fsp);
1784                                 /*
1785                                  * We can use fsp->fsp_name here as it has
1786                                  * already been changed to the new name.
1787                                  */
1788                                 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
1789                                 file_set_dosmode(conn,
1790                                                 fsp->fsp_name,
1791                                                 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
1792                                                 NULL,
1793                                                 true);
1794                         }
1795                 }
1796
1797                 /*
1798                  * A rename acts as a new file create w.r.t. allowing an initial delete
1799                  * on close, probably because in Windows there is a new handle to the
1800                  * new file. If initial delete on close was requested but not
1801                  * originally set, we need to set it here. This is probably not 100% correct,
1802                  * but will work for the CIFSFS client which in non-posix mode
1803                  * depends on these semantics. JRA.
1804                  */
1805
1806                 if (create_options & FILE_DELETE_ON_CLOSE) {
1807                         status = can_set_delete_on_close(fsp, 0);
1808
1809                         if (NT_STATUS_IS_OK(status)) {
1810                                 /* Note that here we set the *initial* delete on close flag,
1811                                  * not the regular one. The magic gets handled in close. */
1812                                 fsp->fsp_flags.initial_delete_on_close = true;
1813                         }
1814                 }
1815                 TALLOC_FREE(lck);
1816                 status = NT_STATUS_OK;
1817                 goto out;
1818         }
1819
1820         TALLOC_FREE(lck);
1821
1822         if (errno == ENOTDIR || errno == EISDIR) {
1823                 status = NT_STATUS_OBJECT_NAME_COLLISION;
1824         } else {
1825                 status = map_nt_error_from_unix(errno);
1826         }
1827
1828         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1829                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1830                   smb_fname_str_dbg(smb_fname_dst)));
1831
1832  out:
1833
1834         /*
1835          * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
1836          * See the optimization for same source and destination directory
1837          * above. Only free one in that case.
1838          */
1839         if (parent_dir_fname_src != parent_dir_fname_dst) {
1840                 TALLOC_FREE(parent_dir_fname_src);
1841         }
1842         TALLOC_FREE(parent_dir_fname_dst);
1843         TALLOC_FREE(smb_fname_dst);
1844
1845         return status;
1846 }
1847
1848 /****************************************************************************
1849  The guts of the rename command, split out so it may be called by the NT SMB
1850  code.
1851 ****************************************************************************/
1852
1853 NTSTATUS rename_internals(TALLOC_CTX *ctx,
1854                         connection_struct *conn,
1855                         struct smb_request *req,
1856                         struct files_struct *src_dirfsp,
1857                         struct smb_filename *smb_fname_src,
1858                         struct smb_filename *smb_fname_dst,
1859                         const char *dst_original_lcomp,
1860                         uint32_t attrs,
1861                         bool replace_if_exists,
1862                         uint32_t access_mask)
1863 {
1864         NTSTATUS status = NT_STATUS_OK;
1865         int create_options = FILE_OPEN_REPARSE_POINT;
1866         struct smb2_create_blobs *posx = NULL;
1867         struct files_struct *fsp = NULL;
1868         bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
1869         bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
1870         bool case_preserve = posix_pathname ? true : conn->case_preserve;
1871         bool short_case_preserve = posix_pathname ? true :
1872                                         conn->short_case_preserve;
1873
1874         if (posix_pathname) {
1875                 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
1876                 if (!NT_STATUS_IS_OK(status)) {
1877                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
1878                                     nt_errstr(status));
1879                         goto out;
1880                 }
1881         }
1882
1883         DBG_NOTICE("case_sensitive = %d, "
1884                   "case_preserve = %d, short case preserve = %d, "
1885                   "directory = %s, newname = %s, "
1886                   "last_component_dest = %s\n",
1887                   case_sensitive, case_preserve,
1888                   short_case_preserve,
1889                   smb_fname_str_dbg(smb_fname_src),
1890                   smb_fname_str_dbg(smb_fname_dst),
1891                   dst_original_lcomp);
1892
1893         ZERO_STRUCT(smb_fname_src->st);
1894
1895         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 if (!NT_STATUS_EQUAL(status,
1898                                 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1899                         goto out;
1900                 }
1901                 /*
1902                  * Possible symlink src.
1903                  */
1904                 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
1905                         goto out;
1906                 }
1907                 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
1908                         goto out;
1909                 }
1910         }
1911
1912         if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
1913                 create_options |= FILE_DIRECTORY_FILE;
1914         }
1915
1916         status = SMB_VFS_CREATE_FILE(
1917                         conn,                           /* conn */
1918                         req,                            /* req */
1919                         src_dirfsp,                     /* dirfsp */
1920                         smb_fname_src,                  /* fname */
1921                         access_mask,                    /* access_mask */
1922                         (FILE_SHARE_READ |              /* share_access */
1923                             FILE_SHARE_WRITE),
1924                         FILE_OPEN,                      /* create_disposition*/
1925                         create_options,                 /* create_options */
1926                         0,                              /* file_attributes */
1927                         0,                              /* oplock_request */
1928                         NULL,                           /* lease */
1929                         0,                              /* allocation_size */
1930                         0,                              /* private_flags */
1931                         NULL,                           /* sd */
1932                         NULL,                           /* ea_list */
1933                         &fsp,                           /* result */
1934                         NULL,                           /* pinfo */
1935                         posx,                           /* in_context_blobs */
1936                         NULL);                          /* out_context_blobs */
1937
1938         if (!NT_STATUS_IS_OK(status)) {
1939                 DBG_NOTICE("Could not open rename source %s: %s\n",
1940                           smb_fname_str_dbg(smb_fname_src),
1941                           nt_errstr(status));
1942                 goto out;
1943         }
1944
1945         status = rename_internals_fsp(conn,
1946                                         fsp,
1947                                         smb_fname_dst,
1948                                         dst_original_lcomp,
1949                                         attrs,
1950                                         replace_if_exists);
1951
1952         close_file_free(req, &fsp, NORMAL_CLOSE);
1953
1954         DBG_NOTICE("Error %s rename %s -> %s\n",
1955                   nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
1956                   smb_fname_str_dbg(smb_fname_dst));
1957
1958  out:
1959         TALLOC_FREE(posx);
1960         return status;
1961 }
1962
1963 /*******************************************************************
1964  Copy a file as part of a reply_copy.
1965 ******************************************************************/
1966
1967 /*
1968  * TODO: check error codes on all callers
1969  */
1970
1971 NTSTATUS copy_file(TALLOC_CTX *ctx,
1972                         connection_struct *conn,
1973                         struct smb_filename *smb_fname_src,
1974                         struct smb_filename *smb_fname_dst,
1975                         uint32_t new_create_disposition)
1976 {
1977         struct smb_filename *smb_fname_dst_tmp = NULL;
1978         off_t ret=-1;
1979         files_struct *fsp1,*fsp2;
1980         uint32_t dosattrs;
1981         NTSTATUS status;
1982
1983
1984         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
1985         if (smb_fname_dst_tmp == NULL) {
1986                 return NT_STATUS_NO_MEMORY;
1987         }
1988
1989         status = vfs_file_exist(conn, smb_fname_src);
1990         if (!NT_STATUS_IS_OK(status)) {
1991                 goto out;
1992         }
1993
1994         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
1995         if (!NT_STATUS_IS_OK(status)) {
1996                 goto out;
1997         }
1998
1999         /* Open the src file for reading. */
2000         status = SMB_VFS_CREATE_FILE(
2001                 conn,                                   /* conn */
2002                 NULL,                                   /* req */
2003                 NULL,                                   /* dirfsp */
2004                 smb_fname_src,                          /* fname */
2005                 FILE_GENERIC_READ,                      /* access_mask */
2006                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2007                 FILE_OPEN,                              /* create_disposition*/
2008                 0,                                      /* create_options */
2009                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
2010                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
2011                 NULL,                                   /* lease */
2012                 0,                                      /* allocation_size */
2013                 0,                                      /* private_flags */
2014                 NULL,                                   /* sd */
2015                 NULL,                                   /* ea_list */
2016                 &fsp1,                                  /* result */
2017                 NULL,                                   /* psbuf */
2018                 NULL, NULL);                            /* create context */
2019
2020         if (!NT_STATUS_IS_OK(status)) {
2021                 goto out;
2022         }
2023
2024         dosattrs = fdos_mode(fsp1);
2025
2026         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
2027                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
2028         }
2029
2030         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
2031         if (!NT_STATUS_IS_OK(status) &&
2032             !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
2033         {
2034                 goto out;
2035         }
2036
2037         /* Open the dst file for writing. */
2038         status = SMB_VFS_CREATE_FILE(
2039                 conn,                                   /* conn */
2040                 NULL,                                   /* req */
2041                 NULL,                                   /* dirfsp */
2042                 smb_fname_dst,                          /* fname */
2043                 FILE_GENERIC_WRITE,                     /* access_mask */
2044                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2045                 new_create_disposition,                 /* create_disposition*/
2046                 0,                                      /* create_options */
2047                 dosattrs,                               /* file_attributes */
2048                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
2049                 NULL,                                   /* lease */
2050                 0,                                      /* allocation_size */
2051                 0,                                      /* private_flags */
2052                 NULL,                                   /* sd */
2053                 NULL,                                   /* ea_list */
2054                 &fsp2,                                  /* result */
2055                 NULL,                                   /* psbuf */
2056                 NULL, NULL);                            /* create context */
2057
2058         if (!NT_STATUS_IS_OK(status)) {
2059                 close_file_free(NULL, &fsp1, ERROR_CLOSE);
2060                 goto out;
2061         }
2062
2063         /* Do the actual copy. */
2064         if (smb_fname_src->st.st_ex_size) {
2065                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
2066         } else {
2067                 ret = 0;
2068         }
2069
2070         close_file_free(NULL, &fsp1, NORMAL_CLOSE);
2071
2072         /* Ensure the modtime is set correctly on the destination file. */
2073         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
2074
2075         /*
2076          * As we are opening fsp1 read-only we only expect
2077          * an error on close on fsp2 if we are out of space.
2078          * Thus we don't look at the error return from the
2079          * close of fsp1.
2080          */
2081         status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
2082
2083         if (!NT_STATUS_IS_OK(status)) {
2084                 goto out;
2085         }
2086
2087         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
2088                 status = NT_STATUS_DISK_FULL;
2089                 goto out;
2090         }
2091
2092         status = NT_STATUS_OK;
2093
2094  out:
2095         TALLOC_FREE(smb_fname_dst_tmp);
2096         return status;
2097 }
2098
2099 /****************************************************************************
2100  Get a lock offset, dealing with large offset requests.
2101 ****************************************************************************/
2102
2103 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
2104                          bool large_file_format)
2105 {
2106         uint64_t offset = 0;
2107
2108         if(!large_file_format) {
2109                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
2110         } else {
2111                 /*
2112                  * No BVAL, this is reversed!
2113                  */
2114                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
2115                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
2116         }
2117
2118         return offset;
2119 }
2120
2121 struct smbd_do_unlocking_state {
2122         struct files_struct *fsp;
2123         uint16_t num_ulocks;
2124         struct smbd_lock_element *ulocks;
2125         NTSTATUS status;
2126 };
2127
2128 static void smbd_do_unlocking_fn(
2129         struct share_mode_lock *lck,
2130         void *private_data)
2131 {
2132         struct smbd_do_unlocking_state *state = private_data;
2133         struct files_struct *fsp = state->fsp;
2134         uint16_t i;
2135
2136         for (i = 0; i < state->num_ulocks; i++) {
2137                 struct smbd_lock_element *e = &state->ulocks[i];
2138
2139                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
2140                           "pid %"PRIu64", file %s\n",
2141                           e->offset,
2142                           e->count,
2143                           e->smblctx,
2144                           fsp_str_dbg(fsp));
2145
2146                 if (e->brltype != UNLOCK_LOCK) {
2147                         /* this can only happen with SMB2 */
2148                         state->status = NT_STATUS_INVALID_PARAMETER;
2149                         return;
2150                 }
2151
2152                 state->status = do_unlock(
2153                         fsp, e->smblctx, e->count, e->offset, e->lock_flav);
2154
2155                 DBG_DEBUG("do_unlock returned %s\n",
2156                           nt_errstr(state->status));
2157
2158                 if (!NT_STATUS_IS_OK(state->status)) {
2159                         return;
2160                 }
2161         }
2162
2163         share_mode_wakeup_waiters(fsp->file_id);
2164 }
2165
2166 NTSTATUS smbd_do_unlocking(struct smb_request *req,
2167                            files_struct *fsp,
2168                            uint16_t num_ulocks,
2169                            struct smbd_lock_element *ulocks)
2170 {
2171         struct smbd_do_unlocking_state state = {
2172                 .fsp = fsp,
2173                 .num_ulocks = num_ulocks,
2174                 .ulocks = ulocks,
2175         };
2176         NTSTATUS status;
2177
2178         DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
2179
2180         status = share_mode_do_locked_vfs_allowed(
2181                 fsp->file_id, smbd_do_unlocking_fn, &state);
2182
2183         if (!NT_STATUS_IS_OK(status)) {
2184                 DBG_DEBUG("share_mode_do_locked_vfs_allowed failed: %s\n",
2185                           nt_errstr(status));
2186                 return status;
2187         }
2188         if (!NT_STATUS_IS_OK(state.status)) {
2189                 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
2190                           nt_errstr(status));
2191                 return state.status;
2192         }
2193
2194         return NT_STATUS_OK;
2195 }