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