s3: smbd: unlink_internals() can figure out if the mask has a wildcard on its own.
[amitay/samba.git] / source3 / smbd / 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 "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
50 #include "lib/util/string_wrappers.h"
51
52 /****************************************************************************
53  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
54  path or anything including wildcards.
55  We're assuming here that '/' is not the second byte in any multibyte char
56  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
57  set.
58 ****************************************************************************/
59
60 /* Custom version for processing POSIX paths. */
61 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
62
63 static NTSTATUS check_path_syntax_internal(char *path,
64                                            bool posix_path,
65                                            bool *p_last_component_contains_wcard)
66 {
67         char *d = path;
68         const char *s = path;
69         NTSTATUS ret = NT_STATUS_OK;
70         bool start_of_name_component = True;
71         bool stream_started = false;
72
73         *p_last_component_contains_wcard = False;
74
75         while (*s) {
76                 if (stream_started) {
77                         switch (*s) {
78                         case '/':
79                         case '\\':
80                                 return NT_STATUS_OBJECT_NAME_INVALID;
81                         case ':':
82                                 if (s[1] == '\0') {
83                                         return NT_STATUS_OBJECT_NAME_INVALID;
84                                 }
85                                 if (strchr_m(&s[1], ':')) {
86                                         return NT_STATUS_OBJECT_NAME_INVALID;
87                                 }
88                                 break;
89                         }
90                 }
91
92                 if ((*s == ':') && !posix_path && !stream_started) {
93                         if (*p_last_component_contains_wcard) {
94                                 return NT_STATUS_OBJECT_NAME_INVALID;
95                         }
96                         /* Stream names allow more characters than file names.
97                            We're overloading posix_path here to allow a wider
98                            range of characters. If stream_started is true this
99                            is still a Windows path even if posix_path is true.
100                            JRA.
101                         */
102                         stream_started = true;
103                         start_of_name_component = false;
104                         posix_path = true;
105
106                         if (s[1] == '\0') {
107                                 return NT_STATUS_OBJECT_NAME_INVALID;
108                         }
109                 }
110
111                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
112                         /*
113                          * Safe to assume is not the second part of a mb char
114                          * as this is handled below.
115                          */
116                         /* Eat multiple '/' or '\\' */
117                         while (IS_PATH_SEP(*s,posix_path)) {
118                                 s++;
119                         }
120                         if ((d != path) && (*s != '\0')) {
121                                 /* We only care about non-leading or trailing '/' or '\\' */
122                                 *d++ = '/';
123                         }
124
125                         start_of_name_component = True;
126                         /* New component. */
127                         *p_last_component_contains_wcard = False;
128                         continue;
129                 }
130
131                 if (start_of_name_component) {
132                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
133                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
134
135                                 /*
136                                  * No mb char starts with '.' so we're safe checking the directory separator here.
137                                  */
138
139                                 /* If  we just added a '/' - delete it */
140                                 if ((d > path) && (*(d-1) == '/')) {
141                                         *(d-1) = '\0';
142                                         d--;
143                                 }
144
145                                 /* Are we at the start ? Can't go back further if so. */
146                                 if (d <= path) {
147                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
148                                         break;
149                                 }
150                                 /* Go back one level... */
151                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
152                                 /* NOTE - if this assumption is invalid we are not in good shape... */
153                                 /* Decrement d first as d points to the *next* char to write into. */
154                                 for (d--; d > path; d--) {
155                                         if (*d == '/')
156                                                 break;
157                                 }
158                                 s += 2; /* Else go past the .. */
159                                 /* We're still at the start of a name component, just the previous one. */
160                                 continue;
161
162                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
163                                 if (posix_path) {
164                                         /* Eat the '.' */
165                                         s++;
166                                         continue;
167                                 }
168                         }
169
170                 }
171
172                 if (!(*s & 0x80)) {
173                         if (!posix_path) {
174                                 if (*s <= 0x1f || *s == '|') {
175                                         return NT_STATUS_OBJECT_NAME_INVALID;
176                                 }
177                                 switch (*s) {
178                                         case '*':
179                                         case '?':
180                                         case '<':
181                                         case '>':
182                                         case '"':
183                                                 *p_last_component_contains_wcard = True;
184                                                 break;
185                                         default:
186                                                 break;
187                                 }
188                         }
189                         *d++ = *s++;
190                 } else {
191                         size_t siz;
192                         /* Get the size of the next MB character. */
193                         next_codepoint(s,&siz);
194                         switch(siz) {
195                                 case 5:
196                                         *d++ = *s++;
197                                         FALL_THROUGH;
198                                 case 4:
199                                         *d++ = *s++;
200                                         FALL_THROUGH;
201                                 case 3:
202                                         *d++ = *s++;
203                                         FALL_THROUGH;
204                                 case 2:
205                                         *d++ = *s++;
206                                         FALL_THROUGH;
207                                 case 1:
208                                         *d++ = *s++;
209                                         break;
210                                 default:
211                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
212                                         *d = '\0';
213                                         return NT_STATUS_INVALID_PARAMETER;
214                         }
215                 }
216                 start_of_name_component = False;
217         }
218
219         *d = '\0';
220
221         return ret;
222 }
223
224 /****************************************************************************
225  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226  No wildcards allowed.
227 ****************************************************************************/
228
229 NTSTATUS check_path_syntax(char *path)
230 {
231         bool ignore;
232         return check_path_syntax_internal(path, False, &ignore);
233 }
234
235 /****************************************************************************
236  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
237  Wildcards allowed - p_contains_wcard returns true if the last component contained
238  a wildcard.
239 ****************************************************************************/
240
241 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
242 {
243         return check_path_syntax_internal(path, False, p_contains_wcard);
244 }
245
246 /****************************************************************************
247  Check the path for a POSIX client.
248  We're assuming here that '/' is not the second byte in any multibyte char
249  set (a safe assumption).
250 ****************************************************************************/
251
252 NTSTATUS check_path_syntax_posix(char *path)
253 {
254         bool ignore;
255         return check_path_syntax_internal(path, True, &ignore);
256 }
257
258 /****************************************************************************
259  Pull a string and check the path allowing a wildcard - provide for error return.
260  Passes in posix flag.
261 ****************************************************************************/
262
263 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
264                         const char *base_ptr,
265                         uint16_t smb_flags2,
266                         char **pp_dest,
267                         const char *src,
268                         size_t src_len,
269                         int flags,
270                         bool posix_pathnames,
271                         NTSTATUS *err,
272                         bool *contains_wcard)
273 {
274         size_t ret;
275
276         *pp_dest = NULL;
277
278         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
279                                  src_len, flags);
280
281         if (!*pp_dest) {
282                 *err = NT_STATUS_INVALID_PARAMETER;
283                 return ret;
284         }
285
286         *contains_wcard = False;
287
288         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
289                 /*
290                  * For a DFS path the function parse_dfs_path()
291                  * will do the path processing, just make a copy.
292                  */
293                 *err = NT_STATUS_OK;
294                 return ret;
295         }
296
297         if (posix_pathnames) {
298                 *err = check_path_syntax_posix(*pp_dest);
299         } else {
300                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
301         }
302
303         return ret;
304 }
305
306 /****************************************************************************
307  Pull a string and check the path allowing a wildcard - provide for error return.
308 ****************************************************************************/
309
310 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
311                         const char *base_ptr,
312                         uint16_t smb_flags2,
313                         char **pp_dest,
314                         const char *src,
315                         size_t src_len,
316                         int flags,
317                         NTSTATUS *err,
318                         bool *contains_wcard)
319 {
320         return srvstr_get_path_wcard_internal(ctx,
321                         base_ptr,
322                         smb_flags2,
323                         pp_dest,
324                         src,
325                         src_len,
326                         flags,
327                         false,
328                         err,
329                         contains_wcard);
330 }
331
332 /****************************************************************************
333  Pull a string and check the path allowing a wildcard - provide for error return.
334  posix_pathnames version.
335 ****************************************************************************/
336
337 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
338                         const char *base_ptr,
339                         uint16_t smb_flags2,
340                         char **pp_dest,
341                         const char *src,
342                         size_t src_len,
343                         int flags,
344                         NTSTATUS *err,
345                         bool *contains_wcard)
346 {
347         return srvstr_get_path_wcard_internal(ctx,
348                         base_ptr,
349                         smb_flags2,
350                         pp_dest,
351                         src,
352                         src_len,
353                         flags,
354                         true,
355                         err,
356                         contains_wcard);
357 }
358
359 /****************************************************************************
360  Pull a string and check the path - provide for error return.
361 ****************************************************************************/
362
363 size_t srvstr_get_path(TALLOC_CTX *ctx,
364                         const char *base_ptr,
365                         uint16_t smb_flags2,
366                         char **pp_dest,
367                         const char *src,
368                         size_t src_len,
369                         int flags,
370                         NTSTATUS *err)
371 {
372         bool ignore;
373         return srvstr_get_path_wcard_internal(ctx,
374                         base_ptr,
375                         smb_flags2,
376                         pp_dest,
377                         src,
378                         src_len,
379                         flags,
380                         false,
381                         err,
382                         &ignore);
383 }
384
385 /****************************************************************************
386  Pull a string and check the path - provide for error return.
387  posix_pathnames version.
388 ****************************************************************************/
389
390 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
391                         const char *base_ptr,
392                         uint16_t smb_flags2,
393                         char **pp_dest,
394                         const char *src,
395                         size_t src_len,
396                         int flags,
397                         NTSTATUS *err)
398 {
399         bool ignore;
400         return srvstr_get_path_wcard_internal(ctx,
401                         base_ptr,
402                         smb_flags2,
403                         pp_dest,
404                         src,
405                         src_len,
406                         flags,
407                         true,
408                         err,
409                         &ignore);
410 }
411
412
413 static size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
414                                  char **pp_dest, const char *src, int flags,
415                                  NTSTATUS *err, bool *contains_wcard)
416 {
417         ssize_t bufrem = smbreq_bufrem(req, src);
418
419         if (bufrem < 0) {
420                 *err = NT_STATUS_INVALID_PARAMETER;
421                 return 0;
422         }
423
424         if (req->posix_pathnames) {
425                 return srvstr_get_path_wcard_internal(mem_ctx,
426                                 (const char *)req->inbuf,
427                                 req->flags2,
428                                 pp_dest,
429                                 src,
430                                 bufrem,
431                                 flags,
432                                 true,
433                                 err,
434                                 contains_wcard);
435         } else {
436                 return srvstr_get_path_wcard_internal(mem_ctx,
437                                 (const char *)req->inbuf,
438                                 req->flags2,
439                                 pp_dest,
440                                 src,
441                                 bufrem,
442                                 flags,
443                                 false,
444                                 err,
445                                 contains_wcard);
446         }
447 }
448
449 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
450                            char **pp_dest, const char *src, int flags,
451                            NTSTATUS *err)
452 {
453         bool ignore;
454         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
455                                          flags, err, &ignore);
456 }
457
458 /**
459  * pull a string from the smb_buf part of a packet. In this case the
460  * string can either be null terminated or it can be terminated by the
461  * end of the smbbuf area
462  */
463 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
464                               char **dest, const uint8_t *src, int flags)
465 {
466         ssize_t bufrem = smbreq_bufrem(req, src);
467
468         if (bufrem < 0) {
469                 return 0;
470         }
471
472         return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
473                                   bufrem, flags);
474 }
475
476 /****************************************************************************
477  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
478 ****************************************************************************/
479
480 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
481                     files_struct *fsp)
482 {
483         if ((fsp == NULL) || (conn == NULL)) {
484                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
485                 return False;
486         }
487         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
488                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
489                 return False;
490         }
491         return True;
492 }
493
494 /****************************************************************************
495  Check if we have a correct fsp pointing to a file.
496 ****************************************************************************/
497
498 bool check_fsp(connection_struct *conn, struct smb_request *req,
499                files_struct *fsp)
500 {
501         if (!check_fsp_open(conn, req, fsp)) {
502                 return False;
503         }
504         if (fsp->fsp_flags.is_directory) {
505                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
506                 return False;
507         }
508         if (fsp->fh->fd == -1) {
509                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
510                 return False;
511         }
512         fsp->num_smb_operations++;
513         return True;
514 }
515
516 /****************************************************************************
517  Check if we have a correct fsp pointing to a quota fake file. Replacement for
518  the CHECK_NTQUOTA_HANDLE_OK macro.
519 ****************************************************************************/
520
521 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
522                               files_struct *fsp)
523 {
524         if (!check_fsp_open(conn, req, fsp)) {
525                 return false;
526         }
527
528         if (fsp->fsp_flags.is_directory) {
529                 return false;
530         }
531
532         if (fsp->fake_file_handle == NULL) {
533                 return false;
534         }
535
536         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
537                 return false;
538         }
539
540         if (fsp->fake_file_handle->private_data == NULL) {
541                 return false;
542         }
543
544         return true;
545 }
546
547 /****************************************************************************
548  Return the port number we've bound to on a socket.
549 ****************************************************************************/
550
551 static int get_socket_port(int fd)
552 {
553         struct samba_sockaddr saddr = {
554                 .sa_socklen = sizeof(struct sockaddr_storage),
555         };
556
557         if (fd == -1) {
558                 return -1;
559         }
560
561         if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
562                 int level = (errno == ENOTCONN) ? 2 : 0;
563                 DEBUG(level, ("getsockname failed. Error was %s\n",
564                                strerror(errno)));
565                 return -1;
566         }
567
568 #if defined(HAVE_IPV6)
569         if (saddr.u.sa.sa_family == AF_INET6) {
570                 return ntohs(saddr.u.in6.sin6_port);
571         }
572 #endif
573         if (saddr.u.sa.sa_family == AF_INET) {
574                 return ntohs(saddr.u.in.sin_port);
575         }
576         return -1;
577 }
578
579 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
580                                      const char *name, int name_type)
581 {
582         char *trim_name;
583         char *trim_name_type;
584         const char *retarget_parm;
585         char *retarget;
586         char *p;
587         int retarget_type = 0x20;
588         int retarget_port = NBT_SMB_PORT;
589         struct sockaddr_storage retarget_addr;
590         struct sockaddr_in *in_addr;
591         bool ret = false;
592         uint8_t outbuf[10];
593
594         if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
595                 return false;
596         }
597
598         trim_name = talloc_strdup(talloc_tos(), name);
599         if (trim_name == NULL) {
600                 goto fail;
601         }
602         trim_char(trim_name, ' ', ' ');
603
604         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
605                                          name_type);
606         if (trim_name_type == NULL) {
607                 goto fail;
608         }
609
610         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
611                                              trim_name_type, NULL);
612         if (retarget_parm == NULL) {
613                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
614                                                      trim_name, NULL);
615         }
616         if (retarget_parm == NULL) {
617                 goto fail;
618         }
619
620         retarget = talloc_strdup(trim_name, retarget_parm);
621         if (retarget == NULL) {
622                 goto fail;
623         }
624
625         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
626
627         p = strchr(retarget, ':');
628         if (p != NULL) {
629                 *p++ = '\0';
630                 retarget_port = atoi(p);
631         }
632
633         p = strchr_m(retarget, '#');
634         if (p != NULL) {
635                 *p++ = '\0';
636                 if (sscanf(p, "%x", &retarget_type) != 1) {
637                         goto fail;
638                 }
639         }
640
641         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
642         if (!ret) {
643                 DEBUG(10, ("could not resolve %s\n", retarget));
644                 goto fail;
645         }
646
647         if (retarget_addr.ss_family != AF_INET) {
648                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
649                 goto fail;
650         }
651
652         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
653
654         _smb_setlen(outbuf, 6);
655         SCVAL(outbuf, 0, 0x84);
656         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
657         *(uint16_t *)(outbuf+8) = htons(retarget_port);
658
659         if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
660                           NULL)) {
661                 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
662                                     "failed.");
663         }
664
665         ret = true;
666  fail:
667         TALLOC_FREE(trim_name);
668         return ret;
669 }
670
671 static void reply_called_name_not_present(char *outbuf)
672 {
673         smb_setlen(outbuf, 1);
674         SCVAL(outbuf, 0, 0x83);
675         SCVAL(outbuf, 4, 0x82);
676 }
677
678 /****************************************************************************
679  Reply to a (netbios-level) special message. 
680 ****************************************************************************/
681
682 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
683 {
684         struct smbd_server_connection *sconn = xconn->client->sconn;
685         int msg_type = CVAL(inbuf,0);
686         int msg_flags = CVAL(inbuf,1);
687         /*
688          * We only really use 4 bytes of the outbuf, but for the smb_setlen
689          * calculation & friends (srv_send_smb uses that) we need the full smb
690          * header.
691          */
692         char outbuf[smb_size];
693
694         memset(outbuf, '\0', sizeof(outbuf));
695
696         smb_setlen(outbuf,0);
697
698         switch (msg_type) {
699         case NBSSrequest: /* session request */
700         {
701                 /* inbuf_size is guarenteed to be at least 4. */
702                 fstring name1,name2;
703                 int name_type1, name_type2;
704                 int name_len1, name_len2;
705
706                 *name1 = *name2 = 0;
707
708                 if (xconn->transport.nbt.got_session) {
709                         exit_server_cleanly("multiple session request not permitted");
710                 }
711
712                 SCVAL(outbuf,0,NBSSpositive);
713                 SCVAL(outbuf,3,0);
714
715                 /* inbuf_size is guaranteed to be at least 4. */
716                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
717                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
718                         DEBUG(0,("Invalid name length in session request\n"));
719                         reply_called_name_not_present(outbuf);
720                         break;
721                 }
722                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
723                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
724                         DEBUG(0,("Invalid name length in session request\n"));
725                         reply_called_name_not_present(outbuf);
726                         break;
727                 }
728
729                 name_type1 = name_extract((unsigned char *)inbuf,
730                                 inbuf_size,(unsigned int)4,name1);
731                 name_type2 = name_extract((unsigned char *)inbuf,
732                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
733
734                 if (name_type1 == -1 || name_type2 == -1) {
735                         DEBUG(0,("Invalid name type in session request\n"));
736                         reply_called_name_not_present(outbuf);
737                         break;
738                 }
739
740                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
741                          name1, name_type1, name2, name_type2));
742
743                 if (netbios_session_retarget(xconn, name1, name_type1)) {
744                         exit_server_cleanly("retargeted client");
745                 }
746
747                 /*
748                  * Windows NT/2k uses "*SMBSERVER" and XP uses
749                  * "*SMBSERV" arrggg!!!
750                  */
751                 if (strequal(name1, "*SMBSERVER     ")
752                     || strequal(name1, "*SMBSERV       "))  {
753                         char *raddr;
754
755                         raddr = tsocket_address_inet_addr_string(sconn->remote_address,
756                                                                  talloc_tos());
757                         if (raddr == NULL) {
758                                 exit_server_cleanly("could not allocate raddr");
759                         }
760
761                         fstrcpy(name1, raddr);
762                 }
763
764                 set_local_machine_name(name1, True);
765                 set_remote_machine_name(name2, True);
766
767                 if (is_ipaddress(sconn->remote_hostname)) {
768                         char *p = discard_const_p(char, sconn->remote_hostname);
769
770                         talloc_free(p);
771
772                         sconn->remote_hostname = talloc_strdup(sconn,
773                                                 get_remote_machine_name());
774                         if (sconn->remote_hostname == NULL) {
775                                 exit_server_cleanly("could not copy remote name");
776                         }
777                         xconn->remote_hostname = sconn->remote_hostname;
778                 }
779
780                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
781                          get_local_machine_name(), get_remote_machine_name(),
782                          name_type2));
783
784                 if (name_type2 == 'R') {
785                         /* We are being asked for a pathworks session --- 
786                            no thanks! */
787                         reply_called_name_not_present(outbuf);
788                         break;
789                 }
790
791                 reload_services(sconn, conn_snum_used, true);
792                 reopen_logs();
793
794                 xconn->transport.nbt.got_session = true;
795                 break;
796         }
797
798         case 0x89: /* session keepalive request 
799                       (some old clients produce this?) */
800                 SCVAL(outbuf,0,NBSSkeepalive);
801                 SCVAL(outbuf,3,0);
802                 break;
803
804         case NBSSpositive: /* positive session response */
805         case NBSSnegative: /* negative session response */
806         case NBSSretarget: /* retarget session response */
807                 DEBUG(0,("Unexpected session response\n"));
808                 break;
809
810         case NBSSkeepalive: /* session keepalive */
811         default:
812                 return;
813         }
814
815         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
816                     msg_type, msg_flags));
817
818         if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
819                 exit_server_cleanly("reply_special: srv_send_smb failed.");
820         }
821
822         if (CVAL(outbuf, 0) != 0x82) {
823                 exit_server_cleanly("invalid netbios session");
824         }
825         return;
826 }
827
828 /****************************************************************************
829  Reply to a tcon.
830  conn POINTER CAN BE NULL HERE !
831 ****************************************************************************/
832
833 void reply_tcon(struct smb_request *req)
834 {
835         connection_struct *conn = req->conn;
836         const char *service;
837         char *service_buf = NULL;
838         char *password = NULL;
839         char *dev = NULL;
840         int pwlen=0;
841         NTSTATUS nt_status;
842         const uint8_t *p;
843         const char *p2;
844         TALLOC_CTX *ctx = talloc_tos();
845         struct smbXsrv_connection *xconn = req->xconn;
846         NTTIME now = timeval_to_nttime(&req->request_time);
847
848         START_PROFILE(SMBtcon);
849
850         if (req->buflen < 4) {
851                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
852                 END_PROFILE(SMBtcon);
853                 return;
854         }
855
856         p = req->buf + 1;
857         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
858         p += 1;
859         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
860         p += pwlen+1;
861         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
862         p += 1;
863
864         if (service_buf == NULL || password == NULL || dev == NULL) {
865                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
866                 END_PROFILE(SMBtcon);
867                 return;
868         }
869         p2 = strrchr_m(service_buf,'\\');
870         if (p2) {
871                 service = p2+1;
872         } else {
873                 service = service_buf;
874         }
875
876         conn = make_connection(req, now, service, dev,
877                                req->vuid,&nt_status);
878         req->conn = conn;
879
880         if (!conn) {
881                 reply_nterror(req, nt_status);
882                 END_PROFILE(SMBtcon);
883                 return;
884         }
885
886         reply_outbuf(req, 2, 0);
887         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
888         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
889         SSVAL(req->outbuf,smb_tid,conn->cnum);
890
891         DEBUG(3,("tcon service=%s cnum=%d\n",
892                  service, conn->cnum));
893
894         END_PROFILE(SMBtcon);
895         return;
896 }
897
898 /****************************************************************************
899  Reply to a tcon and X.
900  conn POINTER CAN BE NULL HERE !
901 ****************************************************************************/
902
903 void reply_tcon_and_X(struct smb_request *req)
904 {
905         const struct loadparm_substitution *lp_sub =
906                 loadparm_s3_global_substitution();
907         connection_struct *conn = req->conn;
908         const char *service = NULL;
909         TALLOC_CTX *ctx = talloc_tos();
910         /* what the client thinks the device is */
911         char *client_devicetype = NULL;
912         /* what the server tells the client the share represents */
913         const char *server_devicetype;
914         NTSTATUS nt_status;
915         int passlen;
916         char *path = NULL;
917         const uint8_t *p;
918         const char *q;
919         uint16_t tcon_flags;
920         struct smbXsrv_session *session = NULL;
921         NTTIME now = timeval_to_nttime(&req->request_time);
922         bool session_key_updated = false;
923         uint16_t optional_support = 0;
924         struct smbXsrv_connection *xconn = req->xconn;
925
926         START_PROFILE(SMBtconX);
927
928         if (req->wct < 4) {
929                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930                 END_PROFILE(SMBtconX);
931                 return;
932         }
933
934         passlen = SVAL(req->vwv+3, 0);
935         tcon_flags = SVAL(req->vwv+2, 0);
936
937         /* we might have to close an old one */
938         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
939                 struct smbXsrv_tcon *tcon;
940                 NTSTATUS status;
941
942                 tcon = conn->tcon;
943                 req->conn = NULL;
944                 conn = NULL;
945
946                 /*
947                  * TODO: cancel all outstanding requests on the tcon
948                  */
949                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
950                 if (!NT_STATUS_IS_OK(status)) {
951                         DEBUG(0, ("reply_tcon_and_X: "
952                                   "smbXsrv_tcon_disconnect() failed: %s\n",
953                                   nt_errstr(status)));
954                         /*
955                          * If we hit this case, there is something completely
956                          * wrong, so we better disconnect the transport connection.
957                          */
958                         END_PROFILE(SMBtconX);
959                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
960                         return;
961                 }
962
963                 TALLOC_FREE(tcon);
964                 /*
965                  * This tree id is gone. Make sure we can't re-use it
966                  * by accident.
967                  */
968                 req->tid = 0;
969         }
970
971         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
972                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
973                 END_PROFILE(SMBtconX);
974                 return;
975         }
976
977         if (xconn->smb1.negprot.encrypted_passwords) {
978                 p = req->buf + passlen;
979         } else {
980                 p = req->buf + passlen + 1;
981         }
982
983         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
984
985         if (path == NULL) {
986                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987                 END_PROFILE(SMBtconX);
988                 return;
989         }
990
991         /*
992          * the service name can be either: \\server\share
993          * or share directly like on the DELL PowerVault 705
994          */
995         if (*path=='\\') {
996                 q = strchr_m(path+2,'\\');
997                 if (!q) {
998                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
999                         END_PROFILE(SMBtconX);
1000                         return;
1001                 }
1002                 service = q+1;
1003         } else {
1004                 service = path;
1005         }
1006
1007         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
1008                                 &client_devicetype, p,
1009                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
1010
1011         if (client_devicetype == NULL) {
1012                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1013                 END_PROFILE(SMBtconX);
1014                 return;
1015         }
1016
1017         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
1018
1019         nt_status = smb1srv_session_lookup(xconn,
1020                                            req->vuid, now, &session);
1021         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
1022                 reply_force_doserror(req, ERRSRV, ERRbaduid);
1023                 END_PROFILE(SMBtconX);
1024                 return;
1025         }
1026         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1027                 reply_nterror(req, nt_status);
1028                 END_PROFILE(SMBtconX);
1029                 return;
1030         }
1031         if (!NT_STATUS_IS_OK(nt_status)) {
1032                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1033                 END_PROFILE(SMBtconX);
1034                 return;
1035         }
1036
1037         if (session->global->auth_session_info == NULL) {
1038                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1039                 END_PROFILE(SMBtconX);
1040                 return;
1041         }
1042
1043         /*
1044          * If there is no application key defined yet
1045          * we create one.
1046          *
1047          * This means we setup the application key on the
1048          * first tcon that happens via the given session.
1049          *
1050          * Once the application key is defined, it does not
1051          * change any more.
1052          */
1053         if (session->global->application_key.length == 0 &&
1054             smb2_signing_key_valid(session->global->signing_key))
1055         {
1056                 struct smbXsrv_session *x = session;
1057                 struct auth_session_info *session_info =
1058                         session->global->auth_session_info;
1059                 uint8_t session_key[16];
1060
1061                 ZERO_STRUCT(session_key);
1062                 memcpy(session_key, x->global->signing_key->blob.data,
1063                        MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1064
1065                 /*
1066                  * The application key is truncated/padded to 16 bytes
1067                  */
1068                 x->global->application_key = data_blob_talloc(x->global,
1069                                                              session_key,
1070                                                              sizeof(session_key));
1071                 ZERO_STRUCT(session_key);
1072                 if (x->global->application_key.data == NULL) {
1073                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1074                         END_PROFILE(SMBtconX);
1075                         return;
1076                 }
1077
1078                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1079                         NTSTATUS status;
1080
1081                         status = smb_key_derivation(x->global->application_key.data,
1082                                                     x->global->application_key.length,
1083                                                     x->global->application_key.data);
1084                         if (!NT_STATUS_IS_OK(status)) {
1085                                 DBG_ERR("smb_key_derivation failed: %s\n",
1086                                         nt_errstr(status));
1087                                 END_PROFILE(SMBtconX);
1088                                 return;
1089                         }
1090                         optional_support |= SMB_EXTENDED_SIGNATURES;
1091                 }
1092
1093                 /*
1094                  * Place the application key into the session_info
1095                  */
1096                 data_blob_clear_free(&session_info->session_key);
1097                 session_info->session_key = data_blob_dup_talloc(session_info,
1098                                                 x->global->application_key);
1099                 if (session_info->session_key.data == NULL) {
1100                         data_blob_clear_free(&x->global->application_key);
1101                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1102                         END_PROFILE(SMBtconX);
1103                         return;
1104                 }
1105                 session_key_updated = true;
1106         }
1107
1108         conn = make_connection(req, now, service, client_devicetype,
1109                                req->vuid, &nt_status);
1110         req->conn =conn;
1111
1112         if (!conn) {
1113                 if (session_key_updated) {
1114                         struct smbXsrv_session *x = session;
1115                         struct auth_session_info *session_info =
1116                                 session->global->auth_session_info;
1117                         data_blob_clear_free(&x->global->application_key);
1118                         data_blob_clear_free(&session_info->session_key);
1119                 }
1120                 reply_nterror(req, nt_status);
1121                 END_PROFILE(SMBtconX);
1122                 return;
1123         }
1124
1125         if ( IS_IPC(conn) )
1126                 server_devicetype = "IPC";
1127         else if ( IS_PRINT(conn) )
1128                 server_devicetype = "LPT1:";
1129         else
1130                 server_devicetype = "A:";
1131
1132         if (get_Protocol() < PROTOCOL_NT1) {
1133                 reply_outbuf(req, 2, 0);
1134                 if (message_push_string(&req->outbuf, server_devicetype,
1135                                         STR_TERMINATE|STR_ASCII) == -1) {
1136                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1137                         END_PROFILE(SMBtconX);
1138                         return;
1139                 }
1140         } else {
1141                 /* NT sets the fstype of IPC$ to the null string */
1142                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1143
1144                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1145                         /* Return permissions. */
1146                         uint32_t perm1 = 0;
1147                         uint32_t perm2 = 0;
1148
1149                         reply_outbuf(req, 7, 0);
1150
1151                         if (IS_IPC(conn)) {
1152                                 perm1 = FILE_ALL_ACCESS;
1153                                 perm2 = FILE_ALL_ACCESS;
1154                         } else {
1155                                 perm1 = conn->share_access;
1156                         }
1157
1158                         SIVAL(req->outbuf, smb_vwv3, perm1);
1159                         SIVAL(req->outbuf, smb_vwv5, perm2);
1160                 } else {
1161                         reply_outbuf(req, 3, 0);
1162                 }
1163
1164                 if ((message_push_string(&req->outbuf, server_devicetype,
1165                                          STR_TERMINATE|STR_ASCII) == -1)
1166                     || (message_push_string(&req->outbuf, fstype,
1167                                             STR_TERMINATE) == -1)) {
1168                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1169                         END_PROFILE(SMBtconX);
1170                         return;
1171                 }
1172
1173                 /* what does setting this bit do? It is set by NT4 and
1174                    may affect the ability to autorun mounted cdroms */
1175                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1176                 optional_support |=
1177                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1178
1179                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1180                         DEBUG(2,("Serving %s as a Dfs root\n",
1181                                  lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1182                         optional_support |= SMB_SHARE_IN_DFS;
1183                 }
1184
1185                 SSVAL(req->outbuf, smb_vwv2, optional_support);
1186         }
1187
1188         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1189         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1190
1191         DEBUG(3,("tconX service=%s \n",
1192                  service));
1193
1194         /* set the incoming and outgoing tid to the just created one */
1195         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1196         SSVAL(req->outbuf,smb_tid,conn->cnum);
1197
1198         END_PROFILE(SMBtconX);
1199
1200         req->tid = conn->cnum;
1201 }
1202
1203 /****************************************************************************
1204  Reply to an unknown type.
1205 ****************************************************************************/
1206
1207 void reply_unknown_new(struct smb_request *req, uint8_t type)
1208 {
1209         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1210                   smb_fn_name(type), type, type));
1211         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1212         return;
1213 }
1214
1215 /****************************************************************************
1216  Reply to an ioctl.
1217  conn POINTER CAN BE NULL HERE !
1218 ****************************************************************************/
1219
1220 void reply_ioctl(struct smb_request *req)
1221 {
1222         const struct loadparm_substitution *lp_sub =
1223                 loadparm_s3_global_substitution();
1224         connection_struct *conn = req->conn;
1225         uint16_t device;
1226         uint16_t function;
1227         uint32_t ioctl_code;
1228         int replysize;
1229         char *p;
1230
1231         START_PROFILE(SMBioctl);
1232
1233         if (req->wct < 3) {
1234                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1235                 END_PROFILE(SMBioctl);
1236                 return;
1237         }
1238
1239         device     = SVAL(req->vwv+1, 0);
1240         function   = SVAL(req->vwv+2, 0);
1241         ioctl_code = (device << 16) + function;
1242
1243         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1244
1245         switch (ioctl_code) {
1246             case IOCTL_QUERY_JOB_INFO:
1247                     replysize = 32;
1248                     break;
1249             default:
1250                     reply_force_doserror(req, ERRSRV, ERRnosupport);
1251                     END_PROFILE(SMBioctl);
1252                     return;
1253         }
1254
1255         reply_outbuf(req, 8, replysize+1);
1256         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1257         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1258         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
1259         p = smb_buf(req->outbuf);
1260         memset(p, '\0', replysize+1); /* valgrind-safe. */
1261         p += 1;          /* Allow for alignment */
1262
1263         switch (ioctl_code) {
1264                 case IOCTL_QUERY_JOB_INFO:                  
1265                 {
1266                         NTSTATUS status;
1267                         size_t len = 0;
1268                         files_struct *fsp = file_fsp(
1269                                 req, SVAL(req->vwv+0, 0));
1270                         if (!fsp) {
1271                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1272                                 END_PROFILE(SMBioctl);
1273                                 return;
1274                         }
1275                         /* Job number */
1276                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1277
1278                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1279                                     lp_netbios_name(), 15,
1280                                     STR_TERMINATE|STR_ASCII, &len);
1281                         if (!NT_STATUS_IS_OK(status)) {
1282                                 reply_nterror(req, status);
1283                                 END_PROFILE(SMBioctl);
1284                                 return;
1285                         }
1286                         if (conn) {
1287                                 status = srvstr_push((char *)req->outbuf, req->flags2,
1288                                             p+18,
1289                                             lp_servicename(talloc_tos(),
1290                                                            lp_sub,
1291                                                            SNUM(conn)),
1292                                             13, STR_TERMINATE|STR_ASCII, &len);
1293                                 if (!NT_STATUS_IS_OK(status)) {
1294                                         reply_nterror(req, status);
1295                                         END_PROFILE(SMBioctl);
1296                                         return;
1297                                 }
1298                         } else {
1299                                 memset(p+18, 0, 13);
1300                         }
1301                         break;
1302                 }
1303         }
1304
1305         END_PROFILE(SMBioctl);
1306         return;
1307 }
1308
1309 /****************************************************************************
1310  Strange checkpath NTSTATUS mapping.
1311 ****************************************************************************/
1312
1313 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1314 {
1315         /* Strange DOS error code semantics only for checkpath... */
1316         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1317                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1318                         /* We need to map to ERRbadpath */
1319                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1320                 }
1321         }
1322         return status;
1323 }
1324
1325 /****************************************************************************
1326  Reply to a checkpath.
1327 ****************************************************************************/
1328
1329 void reply_checkpath(struct smb_request *req)
1330 {
1331         connection_struct *conn = req->conn;
1332         struct smb_filename *smb_fname = NULL;
1333         char *name = NULL;
1334         NTSTATUS status;
1335         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1336         TALLOC_CTX *ctx = talloc_tos();
1337
1338         START_PROFILE(SMBcheckpath);
1339
1340         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1341                             STR_TERMINATE, &status);
1342
1343         if (!NT_STATUS_IS_OK(status)) {
1344                 status = map_checkpath_error(req->flags2, status);
1345                 reply_nterror(req, status);
1346                 END_PROFILE(SMBcheckpath);
1347                 return;
1348         }
1349
1350         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1351
1352         status = filename_convert(ctx,
1353                                 conn,
1354                                 name,
1355                                 ucf_flags,
1356                                 0,
1357                                 NULL,
1358                                 &smb_fname);
1359
1360         if (!NT_STATUS_IS_OK(status)) {
1361                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1362                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1363                                         ERRSRV, ERRbadpath);
1364                         END_PROFILE(SMBcheckpath);
1365                         return;
1366                 }
1367                 goto path_err;
1368         }
1369
1370         if (!VALID_STAT(smb_fname->st) &&
1371             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1372                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1373                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1374                 status = map_nt_error_from_unix(errno);
1375                 goto path_err;
1376         }
1377
1378         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1379                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1380                                 ERRDOS, ERRbadpath);
1381                 goto out;
1382         }
1383
1384         reply_outbuf(req, 0, 0);
1385
1386  path_err:
1387         /* We special case this - as when a Windows machine
1388                 is parsing a path is steps through the components
1389                 one at a time - if a component fails it expects
1390                 ERRbadpath, not ERRbadfile.
1391         */
1392         status = map_checkpath_error(req->flags2, status);
1393         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1394                 /*
1395                  * Windows returns different error codes if
1396                  * the parent directory is valid but not the
1397                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1398                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1399                  * if the path is invalid.
1400                  */
1401                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1402                                 ERRDOS, ERRbadpath);
1403                 goto out;
1404         }
1405
1406         reply_nterror(req, status);
1407
1408  out:
1409         TALLOC_FREE(smb_fname);
1410         END_PROFILE(SMBcheckpath);
1411         return;
1412 }
1413
1414 /****************************************************************************
1415  Reply to a getatr.
1416 ****************************************************************************/
1417
1418 void reply_getatr(struct smb_request *req)
1419 {
1420         connection_struct *conn = req->conn;
1421         struct smb_filename *smb_fname = NULL;
1422         char *fname = NULL;
1423         int mode=0;
1424         off_t size=0;
1425         time_t mtime=0;
1426         const char *p;
1427         NTSTATUS status;
1428         TALLOC_CTX *ctx = talloc_tos();
1429         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1430
1431         START_PROFILE(SMBgetatr);
1432
1433         p = (const char *)req->buf + 1;
1434         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1435         if (!NT_STATUS_IS_OK(status)) {
1436                 reply_nterror(req, status);
1437                 goto out;
1438         }
1439
1440         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1441                 under WfWg - weird! */
1442         if (*fname == '\0') {
1443                 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1444                 if (!CAN_WRITE(conn)) {
1445                         mode |= FILE_ATTRIBUTE_READONLY;
1446                 }
1447                 size = 0;
1448                 mtime = 0;
1449         } else {
1450                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1451                 status = filename_convert(ctx,
1452                                 conn,
1453                                 fname,
1454                                 ucf_flags,
1455                                 0,
1456                                 NULL,
1457                                 &smb_fname);
1458                 if (!NT_STATUS_IS_OK(status)) {
1459                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1460                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1461                                                 ERRSRV, ERRbadpath);
1462                                 goto out;
1463                         }
1464                         reply_nterror(req, status);
1465                         goto out;
1466                 }
1467                 if (!VALID_STAT(smb_fname->st) &&
1468                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1469                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1470                                  smb_fname_str_dbg(smb_fname),
1471                                  strerror(errno)));
1472                         reply_nterror(req,  map_nt_error_from_unix(errno));
1473                         goto out;
1474                 }
1475
1476                 mode = dos_mode(conn, smb_fname);
1477                 size = smb_fname->st.st_ex_size;
1478
1479                 if (ask_sharemode) {
1480                         struct timespec write_time_ts;
1481                         struct file_id fileid;
1482
1483                         ZERO_STRUCT(write_time_ts);
1484                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1485                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1486                         if (!is_omit_timespec(&write_time_ts)) {
1487                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1488                         }
1489                 }
1490
1491                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1492                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1493                         size = 0;
1494                 }
1495         }
1496
1497         reply_outbuf(req, 10, 0);
1498
1499         SSVAL(req->outbuf,smb_vwv0,mode);
1500         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1501                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1502         } else {
1503                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1504         }
1505         SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1506
1507         if (get_Protocol() >= PROTOCOL_NT1) {
1508                 SSVAL(req->outbuf, smb_flg2,
1509                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1510         }
1511
1512         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1513                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1514
1515  out:
1516         TALLOC_FREE(smb_fname);
1517         TALLOC_FREE(fname);
1518         END_PROFILE(SMBgetatr);
1519         return;
1520 }
1521
1522 /****************************************************************************
1523  Reply to a setatr.
1524 ****************************************************************************/
1525
1526 void reply_setatr(struct smb_request *req)
1527 {
1528         struct smb_file_time ft;
1529         connection_struct *conn = req->conn;
1530         struct smb_filename *smb_fname = NULL;
1531         char *fname = NULL;
1532         int mode;
1533         time_t mtime;
1534         const char *p;
1535         NTSTATUS status;
1536         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1537         TALLOC_CTX *ctx = talloc_tos();
1538
1539         START_PROFILE(SMBsetatr);
1540         init_smb_file_time(&ft);
1541
1542         if (req->wct < 2) {
1543                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1544                 goto out;
1545         }
1546
1547         p = (const char *)req->buf + 1;
1548         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1549         if (!NT_STATUS_IS_OK(status)) {
1550                 reply_nterror(req, status);
1551                 goto out;
1552         }
1553
1554         status = filename_convert(ctx,
1555                                 conn,
1556                                 fname,
1557                                 ucf_flags,
1558                                 0,
1559                                 NULL,
1560                                 &smb_fname);
1561         if (!NT_STATUS_IS_OK(status)) {
1562                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1563                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1564                                         ERRSRV, ERRbadpath);
1565                         goto out;
1566                 }
1567                 reply_nterror(req, status);
1568                 goto out;
1569         }
1570
1571         if (ISDOT(smb_fname->base_name)) {
1572                 /*
1573                  * Not sure here is the right place to catch this
1574                  * condition. Might be moved to somewhere else later -- vl
1575                  */
1576                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1577                 goto out;
1578         }
1579
1580         mode = SVAL(req->vwv+0, 0);
1581         mtime = srv_make_unix_date3(req->vwv+1);
1582
1583         if (mode != FILE_ATTRIBUTE_NORMAL) {
1584                 if (VALID_STAT_OF_DIR(smb_fname->st))
1585                         mode |= FILE_ATTRIBUTE_DIRECTORY;
1586                 else
1587                         mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1588
1589                 status = smbd_check_access_rights(conn,
1590                                         conn->cwd_fsp,
1591                                         smb_fname,
1592                                         false,
1593                                         FILE_WRITE_ATTRIBUTES);
1594                 if (!NT_STATUS_IS_OK(status)) {
1595                         reply_nterror(req, status);
1596                         goto out;
1597                 }
1598
1599                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1600                                      false) != 0) {
1601                         reply_nterror(req, map_nt_error_from_unix(errno));
1602                         goto out;
1603                 }
1604         }
1605
1606         ft.mtime = time_t_to_full_timespec(mtime);
1607
1608         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1609         if (!NT_STATUS_IS_OK(status)) {
1610                 reply_nterror(req, status);
1611                 goto out;
1612         }
1613
1614         reply_outbuf(req, 0, 0);
1615
1616         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1617                  mode));
1618  out:
1619         TALLOC_FREE(smb_fname);
1620         END_PROFILE(SMBsetatr);
1621         return;
1622 }
1623
1624 /****************************************************************************
1625  Reply to a dskattr.
1626 ****************************************************************************/
1627
1628 void reply_dskattr(struct smb_request *req)
1629 {
1630         connection_struct *conn = req->conn;
1631         uint64_t ret;
1632         uint64_t dfree,dsize,bsize;
1633         struct smb_filename smb_fname;
1634         START_PROFILE(SMBdskattr);
1635
1636         ZERO_STRUCT(smb_fname);
1637         smb_fname.base_name = discard_const_p(char, ".");
1638
1639         if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1640                 reply_nterror(req, map_nt_error_from_unix(errno));
1641                 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1642                 END_PROFILE(SMBdskattr);
1643                 return;
1644         }
1645
1646         ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1647         if (ret == (uint64_t)-1) {
1648                 reply_nterror(req, map_nt_error_from_unix(errno));
1649                 END_PROFILE(SMBdskattr);
1650                 return;
1651         }
1652
1653         /*
1654          * Force max to fit in 16 bit fields.
1655          */
1656         while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1657                 dfree /= 2;
1658                 dsize /= 2;
1659                 bsize *= 2;
1660                 if (bsize > (WORDMAX*512)) {
1661                         bsize = (WORDMAX*512);
1662                         if (dsize > WORDMAX)
1663                                 dsize = WORDMAX;
1664                         if (dfree >  WORDMAX)
1665                                 dfree = WORDMAX;
1666                         break;
1667                 }
1668         }
1669
1670         reply_outbuf(req, 5, 0);
1671
1672         if (get_Protocol() <= PROTOCOL_LANMAN2) {
1673                 double total_space, free_space;
1674                 /* we need to scale this to a number that DOS6 can handle. We
1675                    use floating point so we can handle large drives on systems
1676                    that don't have 64 bit integers 
1677
1678                    we end up displaying a maximum of 2G to DOS systems
1679                 */
1680                 total_space = dsize * (double)bsize;
1681                 free_space = dfree * (double)bsize;
1682
1683                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1684                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1685
1686                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1687                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1688
1689                 SSVAL(req->outbuf,smb_vwv0,dsize);
1690                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1691                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1692                 SSVAL(req->outbuf,smb_vwv3,dfree);
1693         } else {
1694                 SSVAL(req->outbuf,smb_vwv0,dsize);
1695                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1696                 SSVAL(req->outbuf,smb_vwv2,512);
1697                 SSVAL(req->outbuf,smb_vwv3,dfree);
1698         }
1699
1700         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1701
1702         END_PROFILE(SMBdskattr);
1703         return;
1704 }
1705
1706 /*
1707  * Utility function to split the filename from the directory.
1708  */
1709 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1710                                      char **fname_dir_out,
1711                                      char **fname_mask_out)
1712 {
1713         const char *p = NULL;
1714         char *fname_dir = NULL;
1715         char *fname_mask = NULL;
1716
1717         p = strrchr_m(fname_in, '/');
1718         if (!p) {
1719                 fname_dir = talloc_strdup(ctx, ".");
1720                 fname_mask = talloc_strdup(ctx, fname_in);
1721         } else {
1722                 fname_dir = talloc_strndup(ctx, fname_in,
1723                     PTR_DIFF(p, fname_in));
1724                 fname_mask = talloc_strdup(ctx, p+1);
1725         }
1726
1727         if (!fname_dir || !fname_mask) {
1728                 TALLOC_FREE(fname_dir);
1729                 TALLOC_FREE(fname_mask);
1730                 return NT_STATUS_NO_MEMORY;
1731         }
1732
1733         *fname_dir_out = fname_dir;
1734         *fname_mask_out = fname_mask;
1735         return NT_STATUS_OK;
1736 }
1737
1738 /****************************************************************************
1739  Make a dir struct.
1740 ****************************************************************************/
1741
1742 static bool make_dir_struct(TALLOC_CTX *ctx,
1743                             char *buf,
1744                             const char *mask,
1745                             const char *fname,
1746                             off_t size,
1747                             uint32_t mode,
1748                             time_t date,
1749                             bool uc)
1750 {
1751         char *p;
1752         char *mask2 = talloc_strdup(ctx, mask);
1753
1754         if (!mask2) {
1755                 return False;
1756         }
1757
1758         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1759                 size = 0;
1760         }
1761
1762         memset(buf+1,' ',11);
1763         if ((p = strchr_m(mask2,'.')) != NULL) {
1764                 *p = 0;
1765                 push_ascii(buf+1,mask2,8, 0);
1766                 push_ascii(buf+9,p+1,3, 0);
1767                 *p = '.';
1768         } else {
1769                 push_ascii(buf+1,mask2,11, 0);
1770         }
1771
1772         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1773         SCVAL(buf,21,mode);
1774         srv_put_dos_date(buf,22,date);
1775         SSVAL(buf,26,size & 0xFFFF);
1776         SSVAL(buf,28,(size >> 16)&0xFFFF);
1777         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1778            Strange, but verified on W2K3. Needed for OS/2. JRA. */
1779         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1780         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1781         return True;
1782 }
1783
1784 /****************************************************************************
1785  Reply to a search.
1786  Can be called from SMBsearch, SMBffirst or SMBfunique.
1787 ****************************************************************************/
1788
1789 void reply_search(struct smb_request *req)
1790 {
1791         connection_struct *conn = req->conn;
1792         char *path = NULL;
1793         char *mask = NULL;
1794         char *directory = NULL;
1795         struct smb_filename *smb_fname = NULL;
1796         char *fname = NULL;
1797         off_t size;
1798         uint32_t mode;
1799         struct timespec date;
1800         uint32_t dirtype;
1801         unsigned int numentries = 0;
1802         unsigned int maxentries = 0;
1803         bool finished = False;
1804         const char *p;
1805         int status_len;
1806         char status[21];
1807         int dptr_num= -1;
1808         bool check_descend = False;
1809         bool expect_close = False;
1810         NTSTATUS nt_status;
1811         bool mask_contains_wcard = False;
1812         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1813         TALLOC_CTX *ctx = talloc_tos();
1814         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1815         struct smbXsrv_connection *xconn = req->xconn;
1816         struct smbd_server_connection *sconn = req->sconn;
1817         files_struct *fsp = NULL;
1818         const struct loadparm_substitution *lp_sub =
1819                 loadparm_s3_global_substitution();
1820
1821         START_PROFILE(SMBsearch);
1822
1823         if (req->wct < 2) {
1824                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1825                 goto out;
1826         }
1827
1828         if (req->posix_pathnames) {
1829                 reply_unknown_new(req, req->cmd);
1830                 goto out;
1831         }
1832
1833         /* If we were called as SMBffirst then we must expect close. */
1834         if(req->cmd == SMBffirst) {
1835                 expect_close = True;
1836         }
1837
1838         reply_outbuf(req, 1, 3);
1839         maxentries = SVAL(req->vwv+0, 0);
1840         dirtype = SVAL(req->vwv+1, 0);
1841         p = (const char *)req->buf + 1;
1842         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1843                                        &nt_status);
1844         if (!NT_STATUS_IS_OK(nt_status)) {
1845                 reply_nterror(req, nt_status);
1846                 goto out;
1847         }
1848
1849         if (smbreq_bufrem(req, p) < 3) {
1850                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1851                 goto out;
1852         }
1853
1854         p++;
1855         status_len = SVAL(p, 0);
1856         p += 2;
1857
1858         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1859
1860         if (status_len == 0) {
1861                 int ret;
1862                 struct smb_filename *smb_dname = NULL;
1863                 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1864                         ucf_flags_from_smb_request(req);
1865                 nt_status = filename_convert(ctx, conn,
1866                                              path,
1867                                              ucf_flags,
1868                                              0,
1869                                              NULL,
1870                                              &smb_fname);
1871                 if (!NT_STATUS_IS_OK(nt_status)) {
1872                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1873                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1874                                                 ERRSRV, ERRbadpath);
1875                                 goto out;
1876                         }
1877                         reply_nterror(req, nt_status);
1878                         goto out;
1879                 }
1880
1881                 directory = smb_fname->base_name;
1882
1883                 p = strrchr_m(directory,'/');
1884                 if ((p != NULL) && (*directory != '/')) {
1885                         mask = talloc_strdup(ctx, p + 1);
1886                         directory = talloc_strndup(ctx, directory,
1887                                                    PTR_DIFF(p, directory));
1888                 } else {
1889                         mask = talloc_strdup(ctx, directory);
1890                         directory = talloc_strdup(ctx,".");
1891                 }
1892
1893                 if (!directory) {
1894                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1895                         goto out;
1896                 }
1897
1898                 memset((char *)status,'\0',21);
1899                 SCVAL(status,0,(dirtype & 0x1F));
1900
1901                 smb_dname = synthetic_smb_fname(talloc_tos(),
1902                                         directory,
1903                                         NULL,
1904                                         NULL,
1905                                         smb_fname->twrp,
1906                                         smb_fname->flags);
1907                 if (smb_dname == NULL) {
1908                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1909                         goto out;
1910                 }
1911
1912                 /*
1913                  * As we've cut off the last component from
1914                  * smb_fname we need to re-stat smb_dname
1915                  * so FILE_OPEN disposition knows the directory
1916                  * exists.
1917                  */
1918                 if (req->posix_pathnames) {
1919                         ret = SMB_VFS_LSTAT(conn, smb_dname);
1920                 } else {
1921                         ret = SMB_VFS_STAT(conn, smb_dname);
1922                 }
1923                 if (ret == -1) {
1924                         nt_status = map_nt_error_from_unix(errno);
1925                         reply_nterror(req, nt_status);
1926                         goto out;
1927                 }
1928
1929                 /*
1930                  * Open an fsp on this directory for the dptr.
1931                  */
1932                 nt_status = SMB_VFS_CREATE_FILE(
1933                                 conn, /* conn */
1934                                 req, /* req */
1935                                 &conn->cwd_fsp, /* dirfsp */
1936                                 smb_dname, /* dname */
1937                                 FILE_LIST_DIRECTORY, /* access_mask */
1938                                 FILE_SHARE_READ|
1939                                 FILE_SHARE_WRITE, /* share_access */
1940                                 FILE_OPEN, /* create_disposition*/
1941                                 FILE_DIRECTORY_FILE, /* create_options */
1942                                 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1943                                 NO_OPLOCK, /* oplock_request */
1944                                 NULL, /* lease */
1945                                 0, /* allocation_size */
1946                                 0, /* private_flags */
1947                                 NULL, /* sd */
1948                                 NULL, /* ea_list */
1949                                 &fsp, /* result */
1950                                 NULL, /* pinfo */
1951                                 NULL, /* in_context */
1952                                 NULL);/* out_context */
1953
1954                 if (!NT_STATUS_IS_OK(nt_status)) {
1955                         DBG_ERR("failed to open directory %s\n",
1956                                 smb_fname_str_dbg(smb_dname));
1957                         reply_nterror(req, nt_status);
1958                         goto out;
1959                 }
1960
1961                 nt_status = dptr_create(conn,
1962                                         NULL, /* req */
1963                                         fsp, /* fsp */
1964                                         True,
1965                                         expect_close,
1966                                         req->smbpid,
1967                                         mask,
1968                                         dirtype,
1969                                         &fsp->dptr);
1970
1971                 TALLOC_FREE(smb_dname);
1972
1973                 if (!NT_STATUS_IS_OK(nt_status)) {
1974                         /*
1975                          * Use NULL here for the first parameter (req)
1976                          * as this is not a client visible handle so
1977                          * can'tbe part of an SMB1 chain.
1978                          */
1979                         close_file(NULL, fsp, NORMAL_CLOSE);
1980                         fsp = NULL;
1981                         reply_nterror(req, nt_status);
1982                         goto out;
1983                 }
1984
1985                 dptr_num = dptr_dnum(fsp->dptr);
1986
1987         } else {
1988                 int status_dirtype;
1989                 const char *dirpath;
1990
1991                 if (smbreq_bufrem(req, p) < 21) {
1992                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1993                         goto out;
1994                 }
1995
1996                 memcpy(status,p,21);
1997                 status_dirtype = CVAL(status,0) & 0x1F;
1998                 if (status_dirtype != (dirtype & 0x1F)) {
1999                         dirtype = status_dirtype;
2000                 }
2001
2002                 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2003                 if (fsp == NULL) {
2004                         goto SearchEmpty;
2005                 }
2006                 dirpath = dptr_path(sconn, dptr_num);
2007                 directory = talloc_strdup(ctx, dirpath);
2008                 if (!directory) {
2009                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2010                         goto out;
2011                 }
2012
2013                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
2014                 if (!mask) {
2015                         goto SearchEmpty;
2016                 }
2017                 dirtype = dptr_attr(sconn, dptr_num);
2018         }
2019
2020         mask_contains_wcard = dptr_has_wild(fsp->dptr);
2021
2022         DEBUG(4,("dptr_num is %d\n",dptr_num));
2023
2024         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
2025                 char buf[DIR_STRUCT_SIZE];
2026                 memcpy(buf,status,21);
2027                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
2028                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
2029                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2030                         goto out;
2031                 }
2032                 dptr_fill(sconn, buf+12,dptr_num);
2033                 if (dptr_zero(buf+12) && (status_len==0)) {
2034                         numentries = 1;
2035                 } else {
2036                         numentries = 0;
2037                 }
2038                 if (message_push_blob(&req->outbuf,
2039                                       data_blob_const(buf, sizeof(buf)))
2040                     == -1) {
2041                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2042                         goto out;
2043                 }
2044         } else {
2045                 unsigned int i;
2046                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2047                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2048
2049                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2050
2051                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2052                          directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2053                 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2054                         check_descend = True;
2055                 }
2056
2057                 for (i=numentries;(i<maxentries) && !finished;i++) {
2058                         finished = !get_dir_entry(ctx,
2059                                                   fsp->dptr,
2060                                                   mask,
2061                                                   dirtype,
2062                                                   &fname,
2063                                                   &size,
2064                                                   &mode,
2065                                                   &date,
2066                                                   check_descend,
2067                                                   ask_sharemode);
2068                         if (!finished) {
2069                                 char buf[DIR_STRUCT_SIZE];
2070                                 memcpy(buf,status,21);
2071                                 if (!make_dir_struct(ctx,
2072                                                 buf,
2073                                                 mask,
2074                                                 fname,
2075                                                 size,
2076                                                 mode,
2077                                                 convert_timespec_to_time_t(date),
2078                                                 !allow_long_path_components)) {
2079                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2080                                         goto out;
2081                                 }
2082                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2083                                         break;
2084                                 }
2085                                 if (message_push_blob(&req->outbuf,
2086                                                       data_blob_const(buf, sizeof(buf)))
2087                                     == -1) {
2088                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2089                                         goto out;
2090                                 }
2091                                 numentries++;
2092                         }
2093                 }
2094         }
2095
2096   SearchEmpty:
2097
2098         /* If we were called as SMBffirst with smb_search_id == NULL
2099                 and no entries were found then return error and close fsp->dptr
2100                 (X/Open spec) */
2101
2102         if (numentries == 0) {
2103                 dptr_num = -1;
2104                 if (fsp != NULL) {
2105                         close_file(NULL, fsp, NORMAL_CLOSE);
2106                         fsp = NULL;
2107                 }
2108         } else if(expect_close && status_len == 0) {
2109                 /* Close the dptr - we know it's gone */
2110                 dptr_num = -1;
2111                 if (fsp != NULL) {
2112                         close_file(NULL, fsp, NORMAL_CLOSE);
2113                         fsp = NULL;
2114                 }
2115         }
2116
2117         /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2118         if(dptr_num >= 0 && req->cmd == SMBfunique) {
2119                 dptr_num = -1;
2120                 /* fsp may have been closed above. */
2121                 if (fsp != NULL) {
2122                         close_file(NULL, fsp, NORMAL_CLOSE);
2123                         fsp = NULL;
2124                 }
2125         }
2126
2127         if ((numentries == 0) && !mask_contains_wcard) {
2128                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2129                 goto out;
2130         }
2131
2132         SSVAL(req->outbuf,smb_vwv0,numentries);
2133         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2134         SCVAL(smb_buf(req->outbuf),0,5);
2135         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2136
2137         /* The replies here are never long name. */
2138         SSVAL(req->outbuf, smb_flg2,
2139               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2140         if (!allow_long_path_components) {
2141                 SSVAL(req->outbuf, smb_flg2,
2142                       SVAL(req->outbuf, smb_flg2)
2143                       & (~FLAGS2_LONG_PATH_COMPONENTS));
2144         }
2145
2146         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2147         SSVAL(req->outbuf, smb_flg2,
2148               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2149
2150         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2151                 smb_fn_name(req->cmd),
2152                 mask,
2153                 directory,
2154                 dirtype,
2155                 numentries,
2156                 maxentries ));
2157  out:
2158         TALLOC_FREE(directory);
2159         TALLOC_FREE(mask);
2160         TALLOC_FREE(smb_fname);
2161         END_PROFILE(SMBsearch);
2162         return;
2163 }
2164
2165 /****************************************************************************
2166  Reply to a fclose (stop directory search).
2167 ****************************************************************************/
2168
2169 void reply_fclose(struct smb_request *req)
2170 {
2171         int status_len;
2172         char status[21];
2173         int dptr_num= -2;
2174         const char *p;
2175         char *path = NULL;
2176         NTSTATUS err;
2177         TALLOC_CTX *ctx = talloc_tos();
2178         struct smbd_server_connection *sconn = req->sconn;
2179         files_struct *fsp = NULL;
2180
2181         START_PROFILE(SMBfclose);
2182
2183         if (req->posix_pathnames) {
2184                 reply_unknown_new(req, req->cmd);
2185                 END_PROFILE(SMBfclose);
2186                 return;
2187         }
2188
2189         p = (const char *)req->buf + 1;
2190         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2191                                        &err);
2192         if (!NT_STATUS_IS_OK(err)) {
2193                 reply_nterror(req, err);
2194                 END_PROFILE(SMBfclose);
2195                 return;
2196         }
2197
2198         if (smbreq_bufrem(req, p) < 3) {
2199                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200                 END_PROFILE(SMBfclose);
2201                 return;
2202         }
2203
2204         p++;
2205         status_len = SVAL(p,0);
2206         p += 2;
2207
2208         if (status_len == 0) {
2209                 reply_force_doserror(req, ERRSRV, ERRsrverror);
2210                 END_PROFILE(SMBfclose);
2211                 return;
2212         }
2213
2214         if (smbreq_bufrem(req, p) < 21) {
2215                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2216                 END_PROFILE(SMBfclose);
2217                 return;
2218         }
2219
2220         memcpy(status,p,21);
2221
2222         fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2223         if(fsp != NULL) {
2224                 /*  Close the file - we know it's gone */
2225                 close_file(NULL, fsp, NORMAL_CLOSE);
2226                 fsp = NULL;
2227                 dptr_num = -1;
2228         }
2229
2230         reply_outbuf(req, 1, 0);
2231         SSVAL(req->outbuf,smb_vwv0,0);
2232
2233         DEBUG(3,("search close\n"));
2234
2235         END_PROFILE(SMBfclose);
2236         return;
2237 }
2238
2239 /****************************************************************************
2240  Reply to an open.
2241 ****************************************************************************/
2242
2243 void reply_open(struct smb_request *req)
2244 {
2245         connection_struct *conn = req->conn;
2246         struct smb_filename *smb_fname = NULL;
2247         char *fname = NULL;
2248         uint32_t fattr=0;
2249         off_t size = 0;
2250         time_t mtime=0;
2251         int info;
2252         files_struct *fsp;
2253         int oplock_request;
2254         int deny_mode;
2255         uint32_t dos_attr;
2256         uint32_t access_mask;
2257         uint32_t share_mode;
2258         uint32_t create_disposition;
2259         uint32_t create_options = 0;
2260         uint32_t private_flags = 0;
2261         NTSTATUS status;
2262         uint32_t ucf_flags;
2263         TALLOC_CTX *ctx = talloc_tos();
2264
2265         START_PROFILE(SMBopen);
2266
2267         if (req->wct < 2) {
2268                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2269                 goto out;
2270         }
2271
2272         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2273         deny_mode = SVAL(req->vwv+0, 0);
2274         dos_attr = SVAL(req->vwv+1, 0);
2275
2276         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2277                             STR_TERMINATE, &status);
2278         if (!NT_STATUS_IS_OK(status)) {
2279                 reply_nterror(req, status);
2280                 goto out;
2281         }
2282
2283         if (!map_open_params_to_ntcreate(fname, deny_mode,
2284                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
2285                                          &share_mode, &create_disposition,
2286                                          &create_options, &private_flags)) {
2287                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2288                 goto out;
2289         }
2290
2291         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2292
2293         status = filename_convert(ctx,
2294                                 conn,
2295                                 fname,
2296                                 ucf_flags,
2297                                 0,
2298                                 NULL,
2299                                 &smb_fname);
2300         if (!NT_STATUS_IS_OK(status)) {
2301                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2302                         reply_botherror(req,
2303                                         NT_STATUS_PATH_NOT_COVERED,
2304                                         ERRSRV, ERRbadpath);
2305                         goto out;
2306                 }
2307                 reply_nterror(req, status);
2308                 goto out;
2309         }
2310
2311         status = SMB_VFS_CREATE_FILE(
2312                 conn,                                   /* conn */
2313                 req,                                    /* req */
2314                 &conn->cwd_fsp,                         /* dirfsp */
2315                 smb_fname,                              /* fname */
2316                 access_mask,                            /* access_mask */
2317                 share_mode,                             /* share_access */
2318                 create_disposition,                     /* create_disposition*/
2319                 create_options,                         /* create_options */
2320                 dos_attr,                               /* file_attributes */
2321                 oplock_request,                         /* oplock_request */
2322                 NULL,                                   /* lease */
2323                 0,                                      /* allocation_size */
2324                 private_flags,
2325                 NULL,                                   /* sd */
2326                 NULL,                                   /* ea_list */
2327                 &fsp,                                   /* result */
2328                 &info,                                  /* pinfo */
2329                 NULL, NULL);                            /* create context */
2330
2331         if (!NT_STATUS_IS_OK(status)) {
2332                 if (open_was_deferred(req->xconn, req->mid)) {
2333                         /* We have re-scheduled this call. */
2334                         goto out;
2335                 }
2336
2337                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2338                         reply_openerror(req, status);
2339                         goto out;
2340                 }
2341
2342                 fsp = fcb_or_dos_open(
2343                         req,
2344                         smb_fname,
2345                         access_mask,
2346                         create_options,
2347                         private_flags);
2348                 if (fsp == NULL) {
2349                         bool ok = defer_smb1_sharing_violation(req);
2350                         if (ok) {
2351                                 goto out;
2352                         }
2353                         reply_openerror(req, status);
2354                         goto out;
2355                 }
2356         }
2357
2358         /* Ensure we're pointing at the correct stat struct. */
2359         TALLOC_FREE(smb_fname);
2360         smb_fname = fsp->fsp_name;
2361
2362         size = smb_fname->st.st_ex_size;
2363         fattr = dos_mode(conn, smb_fname);
2364
2365         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2366
2367         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2368                 DEBUG(3,("attempt to open a directory %s\n",
2369                          fsp_str_dbg(fsp)));
2370                 close_file(req, fsp, ERROR_CLOSE);
2371                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2372                         ERRDOS, ERRnoaccess);
2373                 goto out;
2374         }
2375
2376         reply_outbuf(req, 7, 0);
2377         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2378         SSVAL(req->outbuf,smb_vwv1,fattr);
2379         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2380                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2381         } else {
2382                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2383         }
2384         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2385         SSVAL(req->outbuf,smb_vwv6,deny_mode);
2386
2387         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2388                 SCVAL(req->outbuf,smb_flg,
2389                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2390         }
2391
2392         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2393                 SCVAL(req->outbuf,smb_flg,
2394                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2395         }
2396  out:
2397         END_PROFILE(SMBopen);
2398         return;
2399 }
2400
2401 /****************************************************************************
2402  Reply to an open and X.
2403 ****************************************************************************/
2404
2405 void reply_open_and_X(struct smb_request *req)
2406 {
2407         connection_struct *conn = req->conn;
2408         struct smb_filename *smb_fname = NULL;
2409         char *fname = NULL;
2410         uint16_t open_flags;
2411         int deny_mode;
2412         uint32_t smb_attr;
2413         /* Breakout the oplock request bits so we can set the
2414                 reply bits separately. */
2415         int ex_oplock_request;
2416         int core_oplock_request;
2417         int oplock_request;
2418 #if 0
2419         int smb_sattr = SVAL(req->vwv+4, 0);
2420         uint32_t smb_time = make_unix_date3(req->vwv+6);
2421 #endif
2422         int smb_ofun;
2423         uint32_t fattr=0;
2424         int mtime=0;
2425         int smb_action = 0;
2426         files_struct *fsp;
2427         NTSTATUS status;
2428         uint64_t allocation_size;
2429         ssize_t retval = -1;
2430         uint32_t access_mask;
2431         uint32_t share_mode;
2432         uint32_t create_disposition;
2433         uint32_t create_options = 0;
2434         uint32_t private_flags = 0;
2435         uint32_t ucf_flags;
2436         TALLOC_CTX *ctx = talloc_tos();
2437
2438         START_PROFILE(SMBopenX);
2439
2440         if (req->wct < 15) {
2441                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2442                 goto out;
2443         }
2444
2445         open_flags = SVAL(req->vwv+2, 0);
2446         deny_mode = SVAL(req->vwv+3, 0);
2447         smb_attr = SVAL(req->vwv+5, 0);
2448         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2449         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2450         oplock_request = ex_oplock_request | core_oplock_request;
2451         smb_ofun = SVAL(req->vwv+8, 0);
2452         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2453
2454         /* If it's an IPC, pass off the pipe handler. */
2455         if (IS_IPC(conn)) {
2456                 if (lp_nt_pipe_support()) {
2457                         reply_open_pipe_and_X(conn, req);
2458                 } else {
2459                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2460                 }
2461                 goto out;
2462         }
2463
2464         /* XXXX we need to handle passed times, sattr and flags */
2465         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2466                         STR_TERMINATE, &status);
2467         if (!NT_STATUS_IS_OK(status)) {
2468                 reply_nterror(req, status);
2469                 goto out;
2470         }
2471
2472         if (!map_open_params_to_ntcreate(fname, deny_mode,
2473                                          smb_ofun,
2474                                          &access_mask, &share_mode,
2475                                          &create_disposition,
2476                                          &create_options,
2477                                          &private_flags)) {
2478                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2479                 goto out;
2480         }
2481
2482         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2483
2484         status = filename_convert(ctx,
2485                                 conn,
2486                                 fname,
2487                                 ucf_flags,
2488                                 0,
2489                                 NULL,
2490                                 &smb_fname);
2491         if (!NT_STATUS_IS_OK(status)) {
2492                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2493                         reply_botherror(req,
2494                                         NT_STATUS_PATH_NOT_COVERED,
2495                                         ERRSRV, ERRbadpath);
2496                         goto out;
2497                 }
2498                 reply_nterror(req, status);
2499                 goto out;
2500         }
2501
2502         status = SMB_VFS_CREATE_FILE(
2503                 conn,                                   /* conn */
2504                 req,                                    /* req */
2505                 &conn->cwd_fsp,                         /* dirfsp */
2506                 smb_fname,                              /* fname */
2507                 access_mask,                            /* access_mask */
2508                 share_mode,                             /* share_access */
2509                 create_disposition,                     /* create_disposition*/
2510                 create_options,                         /* create_options */
2511                 smb_attr,                               /* file_attributes */
2512                 oplock_request,                         /* oplock_request */
2513                 NULL,                                   /* lease */
2514                 0,                                      /* allocation_size */
2515                 private_flags,
2516                 NULL,                                   /* sd */
2517                 NULL,                                   /* ea_list */
2518                 &fsp,                                   /* result */
2519                 &smb_action,                            /* pinfo */
2520                 NULL, NULL);                            /* create context */
2521
2522         if (!NT_STATUS_IS_OK(status)) {
2523                 if (open_was_deferred(req->xconn, req->mid)) {
2524                         /* We have re-scheduled this call. */
2525                         goto out;
2526                 }
2527
2528                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2529                         reply_openerror(req, status);
2530                         goto out;
2531                 }
2532
2533                 fsp = fcb_or_dos_open(
2534                         req,
2535                         smb_fname,
2536                         access_mask,
2537                         create_options,
2538                         private_flags);
2539                 if (fsp == NULL) {
2540                         bool ok = defer_smb1_sharing_violation(req);
2541                         if (ok) {
2542                                 goto out;
2543                         }
2544                         reply_openerror(req, status);
2545                         goto out;
2546                 }
2547
2548
2549                 smb_action = FILE_WAS_OPENED;
2550         }
2551
2552         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2553            if the file is truncated or created. */
2554         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2555                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2556                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2557                         close_file(req, fsp, ERROR_CLOSE);
2558                         reply_nterror(req, NT_STATUS_DISK_FULL);
2559                         goto out;
2560                 }
2561                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2562                 if (retval < 0) {
2563                         close_file(req, fsp, ERROR_CLOSE);
2564                         reply_nterror(req, NT_STATUS_DISK_FULL);
2565                         goto out;
2566                 }
2567                 status = vfs_stat_fsp(fsp);
2568                 if (!NT_STATUS_IS_OK(status)) {
2569                         close_file(req, fsp, ERROR_CLOSE);
2570                         reply_nterror(req, status);
2571                         goto out;
2572                 }
2573         }
2574
2575         fattr = dos_mode(conn, fsp->fsp_name);
2576         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2577                 close_file(req, fsp, ERROR_CLOSE);
2578                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2579                 goto out;
2580         }
2581         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2582
2583         /* If the caller set the extended oplock request bit
2584                 and we granted one (by whatever means) - set the
2585                 correct bit for extended oplock reply.
2586         */
2587
2588         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2589                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2590         }
2591
2592         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2593                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2594         }
2595
2596         /* If the caller set the core oplock request bit
2597                 and we granted one (by whatever means) - set the
2598                 correct bit for core oplock reply.
2599         */
2600
2601         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602                 reply_outbuf(req, 19, 0);
2603         } else {
2604                 reply_outbuf(req, 15, 0);
2605         }
2606
2607         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2608         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2609
2610         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2611                 SCVAL(req->outbuf, smb_flg,
2612                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2613         }
2614
2615         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2616                 SCVAL(req->outbuf, smb_flg,
2617                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2618         }
2619
2620         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2621         SSVAL(req->outbuf,smb_vwv3,fattr);
2622         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2623                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2624         } else {
2625                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2626         }
2627         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2628         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2629         SSVAL(req->outbuf,smb_vwv11,smb_action);
2630
2631         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2632                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2633         }
2634
2635  out:
2636         TALLOC_FREE(smb_fname);
2637         END_PROFILE(SMBopenX);
2638         return;
2639 }
2640
2641 /****************************************************************************
2642  Reply to a SMBulogoffX.
2643 ****************************************************************************/
2644
2645 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2646                                 struct smbXsrv_session *session);
2647 static void reply_ulogoffX_done(struct tevent_req *req);
2648
2649 void reply_ulogoffX(struct smb_request *smb1req)
2650 {
2651         struct timeval now = timeval_current();
2652         struct smbXsrv_session *session = NULL;
2653         struct tevent_req *req;
2654         NTSTATUS status;
2655
2656         /*
2657          * Don't setup the profile charge here, take
2658          * it in reply_ulogoffX_done(). Not strictly correct
2659          * but better than the other SMB1 async
2660          * code that double-charges at the moment.
2661          */
2662
2663         status = smb1srv_session_lookup(smb1req->xconn,
2664                                         smb1req->vuid,
2665                                         timeval_to_nttime(&now),
2666                                         &session);
2667         if (!NT_STATUS_IS_OK(status)) {
2668                 /* Not going async, profile here. */
2669                 START_PROFILE(SMBulogoffX);
2670                 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2671                          (unsigned long long)smb1req->vuid);
2672
2673                 smb1req->vuid = UID_FIELD_INVALID;
2674                 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2675                 END_PROFILE(SMBulogoffX);
2676                 return;
2677         }
2678
2679         req = reply_ulogoffX_send(smb1req, session);
2680         if (req == NULL) {
2681                 /* Not going async, profile here. */
2682                 START_PROFILE(SMBulogoffX);
2683                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2684                 END_PROFILE(SMBulogoffX);
2685                 return;
2686         }
2687
2688         /* We're async. This will complete later. */
2689         tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2690         return;
2691 }
2692
2693 struct reply_ulogoffX_state {
2694         struct tevent_queue *wait_queue;
2695         struct smbXsrv_session *session;
2696 };
2697
2698 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2699
2700 /****************************************************************************
2701  Async SMB1 ulogoffX.
2702  Note, on failure here we deallocate and return NULL to allow the caller to
2703  SMB1 return an error of ERRnomem immediately.
2704 ****************************************************************************/
2705
2706 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2707                                         struct smbXsrv_session *session)
2708 {
2709         struct tevent_req *req;
2710         struct reply_ulogoffX_state *state;
2711         struct tevent_req *subreq;
2712         files_struct *fsp;
2713         struct smbd_server_connection *sconn = session->client->sconn;
2714         uint64_t vuid = session->global->session_wire_id;
2715
2716         req = tevent_req_create(smb1req, &state,
2717                         struct reply_ulogoffX_state);
2718         if (req == NULL) {
2719                 return NULL;
2720         }
2721         state->wait_queue = tevent_queue_create(state,
2722                                 "reply_ulogoffX_wait_queue");
2723         if (tevent_req_nomem(state->wait_queue, req)) {
2724                 TALLOC_FREE(req);
2725                 return NULL;
2726         }
2727         state->session = session;
2728
2729         /*
2730          * Make sure that no new request will be able to use this session.
2731          * This ensures that once all outstanding fsp->aio_requests
2732          * on this session are done, we are safe to close it.
2733          */
2734         session->status = NT_STATUS_USER_SESSION_DELETED;
2735
2736         for (fsp = sconn->files; fsp; fsp = fsp->next) {
2737                 if (fsp->vuid != vuid) {
2738                         continue;
2739                 }
2740                 /*
2741                  * Flag the file as close in progress.
2742                  * This will prevent any more IO being
2743                  * done on it.
2744                  */
2745                 fsp->fsp_flags.closing = true;
2746
2747                 if (fsp->num_aio_requests > 0) {
2748                         /*
2749                          * Now wait until all aio requests on this fsp are
2750                          * finished.
2751                          *
2752                          * We don't set a callback, as we just want to block the
2753                          * wait queue and the talloc_free() of fsp->aio_request
2754                          * will remove the item from the wait queue.
2755                          */
2756                         subreq = tevent_queue_wait_send(fsp->aio_requests,
2757                                                 sconn->ev_ctx,
2758                                                 state->wait_queue);
2759                         if (tevent_req_nomem(subreq, req)) {
2760                                 TALLOC_FREE(req);
2761                                 return NULL;
2762                         }
2763                 }
2764         }
2765
2766         /*
2767          * Now we add our own waiter to the end of the queue,
2768          * this way we get notified when all pending requests are finished
2769          * and reply to the outstanding SMB1 request.
2770          */
2771         subreq = tevent_queue_wait_send(state,
2772                                 sconn->ev_ctx,
2773                                 state->wait_queue);
2774         if (tevent_req_nomem(subreq, req)) {
2775                 TALLOC_FREE(req);
2776                 return NULL;
2777         }
2778
2779         /*
2780          * We're really going async - move the SMB1 request from
2781          * a talloc stackframe above us to the sconn talloc-context.
2782          * We need this to stick around until the wait_done
2783          * callback is invoked.
2784          */
2785         smb1req = talloc_move(sconn, &smb1req);
2786
2787         tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2788
2789         return req;
2790 }
2791
2792 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2793 {
2794         struct tevent_req *req = tevent_req_callback_data(
2795                 subreq, struct tevent_req);
2796
2797         tevent_queue_wait_recv(subreq);
2798         TALLOC_FREE(subreq);
2799         tevent_req_done(req);
2800 }
2801
2802 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2803 {
2804         return tevent_req_simple_recv_ntstatus(req);
2805 }
2806
2807 static void reply_ulogoffX_done(struct tevent_req *req)
2808 {
2809         struct smb_request *smb1req = tevent_req_callback_data(
2810                 req, struct smb_request);
2811         struct reply_ulogoffX_state *state = tevent_req_data(req,
2812                                                 struct reply_ulogoffX_state);
2813         struct smbXsrv_session *session = state->session;
2814         NTSTATUS status;
2815
2816         /*
2817          * Take the profile charge here. Not strictly
2818          * correct but better than the other SMB1 async
2819          * code that double-charges at the moment.
2820          */
2821         START_PROFILE(SMBulogoffX);
2822
2823         status = reply_ulogoffX_recv(req);
2824         TALLOC_FREE(req);
2825         if (!NT_STATUS_IS_OK(status)) {
2826                 TALLOC_FREE(smb1req);
2827                 END_PROFILE(SMBulogoffX);
2828                 exit_server(__location__ ": reply_ulogoffX_recv failed");
2829                 return;
2830         }
2831
2832         status = smbXsrv_session_logoff(session);
2833         if (!NT_STATUS_IS_OK(status)) {
2834                 TALLOC_FREE(smb1req);
2835                 END_PROFILE(SMBulogoffX);
2836                 exit_server(__location__ ": smbXsrv_session_logoff failed");
2837                 return;
2838         }
2839
2840         TALLOC_FREE(session);
2841
2842         reply_outbuf(smb1req, 2, 0);
2843         SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2844         SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
2845
2846         DBG_NOTICE("ulogoffX vuid=%llu\n",
2847                   (unsigned long long)smb1req->vuid);
2848
2849         smb1req->vuid = UID_FIELD_INVALID;
2850         /*
2851          * The following call is needed to push the
2852          * reply data back out the socket after async
2853          * return. Plus it frees smb1req.
2854          */
2855         smb_request_done(smb1req);
2856         END_PROFILE(SMBulogoffX);
2857 }
2858
2859 /****************************************************************************
2860  Reply to a mknew or a create.
2861 ****************************************************************************/
2862
2863 void reply_mknew(struct smb_request *req)
2864 {
2865         connection_struct *conn = req->conn;
2866         struct smb_filename *smb_fname = NULL;
2867         char *fname = NULL;
2868         uint32_t fattr = 0;
2869         struct smb_file_time ft;
2870         files_struct *fsp;
2871         int oplock_request = 0;
2872         NTSTATUS status;
2873         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2874         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2875         uint32_t create_disposition;
2876         uint32_t create_options = 0;
2877         uint32_t ucf_flags;
2878         TALLOC_CTX *ctx = talloc_tos();
2879
2880         START_PROFILE(SMBcreate);
2881         init_smb_file_time(&ft);
2882
2883         if (req->wct < 3) {
2884                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2885                 goto out;
2886         }
2887
2888         fattr = SVAL(req->vwv+0, 0);
2889         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2890
2891         if (req->cmd == SMBmknew) {
2892                 /* We should fail if file exists. */
2893                 create_disposition = FILE_CREATE;
2894         } else {
2895                 /* Create if file doesn't exist, truncate if it does. */
2896                 create_disposition = FILE_OVERWRITE_IF;
2897         }
2898
2899         /* mtime. */
2900         ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2901
2902         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2903                             STR_TERMINATE, &status);
2904         if (!NT_STATUS_IS_OK(status)) {
2905                 reply_nterror(req, status);
2906                 goto out;
2907         }
2908
2909         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2910         status = filename_convert(ctx,
2911                                 conn,
2912                                 fname,
2913                                 ucf_flags,
2914                                 0,
2915                                 NULL,
2916                                 &smb_fname);
2917         if (!NT_STATUS_IS_OK(status)) {
2918                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2919                         reply_botherror(req,
2920                                         NT_STATUS_PATH_NOT_COVERED,
2921                                         ERRSRV, ERRbadpath);
2922                         goto out;
2923                 }
2924                 reply_nterror(req, status);
2925                 goto out;
2926         }
2927
2928         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2929                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2930                          "please report this\n",
2931                          smb_fname_str_dbg(smb_fname)));
2932         }
2933
2934         status = SMB_VFS_CREATE_FILE(
2935                 conn,                                   /* conn */
2936                 req,                                    /* req */
2937                 &conn->cwd_fsp,                         /* dirfsp */
2938                 smb_fname,                              /* fname */
2939                 access_mask,                            /* access_mask */
2940                 share_mode,                             /* share_access */
2941                 create_disposition,                     /* create_disposition*/
2942                 create_options,                         /* create_options */
2943                 fattr,                                  /* file_attributes */
2944                 oplock_request,                         /* oplock_request */
2945                 NULL,                                   /* lease */
2946                 0,                                      /* allocation_size */
2947                 0,                                      /* private_flags */
2948                 NULL,                                   /* sd */
2949                 NULL,                                   /* ea_list */
2950                 &fsp,                                   /* result */
2951                 NULL,                                   /* pinfo */
2952                 NULL, NULL);                            /* create context */
2953
2954         if (!NT_STATUS_IS_OK(status)) {
2955                 if (open_was_deferred(req->xconn, req->mid)) {
2956                         /* We have re-scheduled this call. */
2957                         goto out;
2958                 }
2959                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2960                         bool ok = defer_smb1_sharing_violation(req);
2961                         if (ok) {
2962                                 goto out;
2963                         }
2964                 }
2965                 reply_openerror(req, status);
2966                 goto out;
2967         }
2968
2969         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2970         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2971         if (!NT_STATUS_IS_OK(status)) {
2972                 END_PROFILE(SMBcreate);
2973                 goto out;
2974         }
2975
2976         reply_outbuf(req, 1, 0);
2977         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2978
2979         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2980                 SCVAL(req->outbuf,smb_flg,
2981                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2982         }
2983
2984         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2985                 SCVAL(req->outbuf,smb_flg,
2986                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2987         }
2988
2989         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2990         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2991                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2992                   (unsigned int)fattr));
2993
2994  out:
2995         TALLOC_FREE(smb_fname);
2996         END_PROFILE(SMBcreate);
2997         return;
2998 }
2999
3000 /****************************************************************************
3001  Reply to a create temporary file.
3002 ****************************************************************************/
3003
3004 void reply_ctemp(struct smb_request *req)
3005 {
3006         connection_struct *conn = req->conn;
3007         struct smb_filename *smb_fname = NULL;
3008         char *wire_name = NULL;
3009         char *fname = NULL;
3010         uint32_t fattr;
3011         files_struct *fsp;
3012         int oplock_request;
3013         char *s;
3014         NTSTATUS status;
3015         int i;
3016         uint32_t ucf_flags;
3017         TALLOC_CTX *ctx = talloc_tos();
3018
3019         START_PROFILE(SMBctemp);
3020
3021         if (req->wct < 3) {
3022                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3023                 goto out;
3024         }
3025
3026         fattr = SVAL(req->vwv+0, 0);
3027         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
3028
3029         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3030                             STR_TERMINATE, &status);
3031         if (!NT_STATUS_IS_OK(status)) {
3032                 reply_nterror(req, status);
3033                 goto out;
3034         }
3035
3036         for (i = 0; i < 10; i++) {
3037                 if (*wire_name) {
3038                         fname = talloc_asprintf(ctx,
3039                                         "%s/TMP%s",
3040                                         wire_name,
3041                                         generate_random_str_list(ctx, 5, "0123456789"));
3042                 } else {
3043                         fname = talloc_asprintf(ctx,
3044                                         "TMP%s",
3045                                         generate_random_str_list(ctx, 5, "0123456789"));
3046                 }
3047
3048                 if (!fname) {
3049                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3050                         goto out;
3051                 }
3052
3053                 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3054                 status = filename_convert(ctx, conn,
3055                                 fname,
3056                                 ucf_flags,
3057                                 0,
3058                                 NULL,
3059                                 &smb_fname);
3060                 if (!NT_STATUS_IS_OK(status)) {
3061                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3062                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3063                                         ERRSRV, ERRbadpath);
3064                                 goto out;
3065                         }
3066                         reply_nterror(req, status);
3067                         goto out;
3068                 }
3069
3070                 /* Create the file. */
3071                 status = SMB_VFS_CREATE_FILE(
3072                         conn,                                   /* conn */
3073                         req,                                    /* req */
3074                         &conn->cwd_fsp,                         /* dirfsp */
3075                         smb_fname,                              /* fname */
3076                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3077                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
3078                         FILE_CREATE,                            /* create_disposition*/
3079                         0,                                      /* create_options */
3080                         fattr,                                  /* file_attributes */
3081                         oplock_request,                         /* oplock_request */
3082                         NULL,                                   /* lease */
3083                         0,                                      /* allocation_size */
3084                         0,                                      /* private_flags */
3085                         NULL,                                   /* sd */
3086                         NULL,                                   /* ea_list */
3087                         &fsp,                                   /* result */
3088                         NULL,                                   /* pinfo */
3089                         NULL, NULL);                            /* create context */
3090
3091                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3092                         TALLOC_FREE(fname);
3093                         TALLOC_FREE(smb_fname);
3094                         continue;
3095                 }
3096
3097                 if (!NT_STATUS_IS_OK(status)) {
3098                         if (open_was_deferred(req->xconn, req->mid)) {
3099                                 /* We have re-scheduled this call. */
3100                                 goto out;
3101                         }
3102                         if (NT_STATUS_EQUAL(
3103                                     status, NT_STATUS_SHARING_VIOLATION)) {
3104                                 bool ok = defer_smb1_sharing_violation(req);
3105                                 if (ok) {
3106                                         goto out;
3107                                 }
3108                         }
3109                         reply_openerror(req, status);
3110                         goto out;
3111                 }
3112
3113                 break;
3114         }
3115
3116         if (i == 10) {
3117                 /* Collision after 10 times... */
3118                 reply_nterror(req, status);
3119                 goto out;
3120         }
3121
3122         reply_outbuf(req, 1, 0);
3123         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3124
3125         /* the returned filename is relative to the directory */
3126         s = strrchr_m(fsp->fsp_name->base_name, '/');
3127         if (!s) {
3128                 s = fsp->fsp_name->base_name;
3129         } else {
3130                 s++;
3131         }
3132
3133 #if 0
3134         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3135            thing in the byte section. JRA */
3136         SSVALS(p, 0, -1); /* what is this? not in spec */
3137 #endif
3138         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3139             == -1) {
3140                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3141                 goto out;
3142         }
3143
3144         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3145                 SCVAL(req->outbuf, smb_flg,
3146                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3147         }
3148
3149         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3150                 SCVAL(req->outbuf, smb_flg,
3151                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3152         }
3153
3154         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3155         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3156                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3157  out:
3158         TALLOC_FREE(smb_fname);
3159         TALLOC_FREE(wire_name);
3160         END_PROFILE(SMBctemp);
3161         return;
3162 }
3163
3164 /*******************************************************************
3165  Check if a user is allowed to rename a file.
3166 ********************************************************************/
3167
3168 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3169                         uint16_t dirtype)
3170 {
3171         if (!CAN_WRITE(conn)) {
3172                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3173         }
3174
3175         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3176                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3177                 /* Only bother to read the DOS attribute if we might deny the
3178                    rename on the grounds of attribute mismatch. */
3179                 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3180                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3181                         return NT_STATUS_NO_SUCH_FILE;
3182                 }
3183         }
3184
3185         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3186                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3187                         return NT_STATUS_OK;
3188                 }
3189
3190                 /* If no pathnames are open below this
3191                    directory, allow the rename. */
3192
3193                 if (lp_strict_rename(SNUM(conn))) {
3194                         /*
3195                          * Strict rename, check open file db.
3196                          */
3197                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3198                                 return NT_STATUS_ACCESS_DENIED;
3199                         }
3200                 } else if (file_find_subpath(fsp)) {
3201                         /*
3202                          * No strict rename, just look in local process.
3203                          */
3204                         return NT_STATUS_ACCESS_DENIED;
3205                 }
3206                 return NT_STATUS_OK;
3207         }
3208
3209         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3210                 return NT_STATUS_OK;
3211         }
3212
3213         return NT_STATUS_ACCESS_DENIED;
3214 }
3215
3216 /*******************************************************************
3217  * unlink a file with all relevant access checks
3218  *******************************************************************/
3219
3220 static NTSTATUS do_unlink(connection_struct *conn,
3221                         struct smb_request *req,
3222                         struct smb_filename *smb_fname,
3223                         uint32_t dirtype)
3224 {
3225         uint32_t fattr;
3226         files_struct *fsp;
3227         uint32_t dirtype_orig = dirtype;
3228         NTSTATUS status;
3229         int ret;
3230         bool posix_paths = (req != NULL && req->posix_pathnames);
3231         struct smb2_create_blobs *posx = NULL;
3232
3233         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3234                   smb_fname_str_dbg(smb_fname),
3235                   dirtype));
3236
3237         if (!CAN_WRITE(conn)) {
3238                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3239         }
3240
3241         if (posix_paths) {
3242                 ret = SMB_VFS_LSTAT(conn, smb_fname);
3243         } else {
3244                 ret = SMB_VFS_STAT(conn, smb_fname);
3245         }
3246         if (ret != 0) {
3247                 return map_nt_error_from_unix(errno);
3248         }
3249
3250         fattr = dos_mode(conn, smb_fname);
3251
3252         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3253                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3254         }
3255
3256         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3257         if (!dirtype) {
3258                 return NT_STATUS_NO_SUCH_FILE;
3259         }
3260
3261         if (!dir_check_ftype(fattr, dirtype)) {
3262                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3263                         return NT_STATUS_FILE_IS_A_DIRECTORY;
3264                 }
3265                 return NT_STATUS_NO_SUCH_FILE;
3266         }
3267
3268         if (dirtype_orig & 0x8000) {
3269                 /* These will never be set for POSIX. */
3270                 return NT_STATUS_NO_SUCH_FILE;
3271         }
3272
3273 #if 0
3274         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3275                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3276         }
3277
3278         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3279                 return NT_STATUS_NO_SUCH_FILE;
3280         }
3281
3282         if (dirtype & 0xFF00) {
3283                 /* These will never be set for POSIX. */
3284                 return NT_STATUS_NO_SUCH_FILE;
3285         }
3286
3287         dirtype &= 0xFF;
3288         if (!dirtype) {
3289                 return NT_STATUS_NO_SUCH_FILE;
3290         }
3291
3292         /* Can't delete a directory. */
3293         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3294                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3295         }
3296 #endif
3297
3298 #if 0 /* JRATEST */
3299         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3300                 return NT_STATUS_OBJECT_NAME_INVALID;
3301 #endif /* JRATEST */
3302
3303         if (posix_paths) {
3304                 status = make_smb2_posix_create_ctx(
3305                         talloc_tos(), &posx, 0777);
3306                 if (!NT_STATUS_IS_OK(status)) {
3307                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3308                                     nt_errstr(status));
3309                         return status;
3310                 }
3311         }
3312
3313         /* On open checks the open itself will check the share mode, so
3314            don't do it here as we'll get it wrong. */
3315
3316         status = SMB_VFS_CREATE_FILE
3317                 (conn,                  /* conn */
3318                  req,                   /* req */
3319                  &conn->cwd_fsp,        /* dirfsp */
3320                  smb_fname,             /* fname */
3321                  DELETE_ACCESS,         /* access_mask */
3322                  FILE_SHARE_NONE,       /* share_access */
3323                  FILE_OPEN,             /* create_disposition*/
3324                  FILE_NON_DIRECTORY_FILE, /* create_options */
3325                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3326                  0,                     /* oplock_request */
3327                  NULL,                  /* lease */
3328                  0,                     /* allocation_size */
3329                  0,                     /* private_flags */
3330                  NULL,                  /* sd */
3331                  NULL,                  /* ea_list */
3332                  &fsp,                  /* result */
3333                  NULL,                  /* pinfo */
3334                  posx,                  /* in_context_blobs */
3335                  NULL);                 /* out_context_blobs */
3336
3337         TALLOC_FREE(posx);
3338
3339         if (!NT_STATUS_IS_OK(status)) {
3340                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3341                            nt_errstr(status)));
3342                 return status;
3343         }
3344
3345         status = can_set_delete_on_close(fsp, fattr);
3346         if (!NT_STATUS_IS_OK(status)) {
3347                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3348                         "(%s)\n",
3349                         smb_fname_str_dbg(smb_fname),
3350                         nt_errstr(status)));
3351                 close_file(req, fsp, NORMAL_CLOSE);
3352                 return status;
3353         }
3354
3355         /* The set is across all open files on this dev/inode pair. */
3356         if (!set_delete_on_close(fsp, True,
3357                                 conn->session_info->security_token,
3358                                 conn->session_info->unix_token)) {
3359                 close_file(req, fsp, NORMAL_CLOSE);
3360                 return NT_STATUS_ACCESS_DENIED;
3361         }
3362
3363         return close_file(req, fsp, NORMAL_CLOSE);
3364 }
3365
3366 /****************************************************************************
3367  The guts of the unlink command, split out so it may be called by the NT SMB
3368  code.
3369 ****************************************************************************/
3370
3371 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3372                           uint32_t dirtype, struct smb_filename *smb_fname)
3373 {
3374         char *fname_dir = NULL;
3375         char *fname_mask = NULL;
3376         int count=0;
3377         NTSTATUS status = NT_STATUS_OK;
3378         struct smb_filename *smb_fname_dir = NULL;
3379         bool has_wild = false;
3380         TALLOC_CTX *ctx = talloc_tos();
3381
3382         /* Split up the directory from the filename/mask. */
3383         status = split_fname_dir_mask(ctx, smb_fname->base_name,
3384                                       &fname_dir, &fname_mask);
3385         if (!NT_STATUS_IS_OK(status)) {
3386                 goto out;
3387         }
3388
3389         if (req != NULL && !req->posix_pathnames) {
3390                 /*
3391                  * Check the wildcard mask *before*
3392                  * unmangling. As mangling is done
3393                  * for names that can't be returned
3394                  * to Windows the unmangled name may
3395                  * contain Windows wildcard characters.
3396                  */
3397                 has_wild = ms_has_wild(fname_mask);
3398         }
3399
3400         /*
3401          * We should only check the mangled cache
3402          * here if unix_convert failed. This means
3403          * that the path in 'mask' doesn't exist
3404          * on the file system and so we need to look
3405          * for a possible mangle. This patch from
3406          * Tine Smukavec <valentin.smukavec@hermes.si>.
3407          */
3408
3409         if (!VALID_STAT(smb_fname->st) &&
3410             mangle_is_mangled(fname_mask, conn->params)) {
3411                 char *new_mask = NULL;
3412                 mangle_lookup_name_from_8_3(ctx, fname_mask,
3413                                             &new_mask, conn->params);
3414                 if (new_mask) {
3415                         TALLOC_FREE(fname_mask);
3416                         fname_mask = new_mask;
3417                 }
3418         }
3419
3420         if (!has_wild) {
3421
3422                 /*
3423                  * Only one file needs to be unlinked. Append the mask back
3424                  * onto the directory.
3425                  */
3426                 TALLOC_FREE(smb_fname->base_name);
3427                 if (ISDOT(fname_dir)) {
3428                         /* Ensure we use canonical names on open. */
3429                         smb_fname->base_name = talloc_asprintf(smb_fname,
3430                                                         "%s",
3431                                                         fname_mask);
3432                 } else {
3433                         smb_fname->base_name = talloc_asprintf(smb_fname,
3434                                                         "%s/%s",
3435                                                         fname_dir,
3436                                                         fname_mask);
3437                 }
3438                 if (!smb_fname->base_name) {
3439                         status = NT_STATUS_NO_MEMORY;
3440                         goto out;
3441                 }
3442                 if (dirtype == 0) {
3443                         dirtype = FILE_ATTRIBUTE_NORMAL;
3444                 }
3445
3446                 status = check_name(conn, smb_fname);
3447                 if (!NT_STATUS_IS_OK(status)) {
3448                         goto out;
3449                 }
3450
3451                 status = do_unlink(conn, req, smb_fname, dirtype);
3452                 if (!NT_STATUS_IS_OK(status)) {
3453                         goto out;
3454                 }
3455
3456                 count++;
3457         } else {
3458                 struct smb_Dir *dir_hnd = NULL;
3459                 long offset = 0;
3460                 const char *dname = NULL;
3461                 char *talloced = NULL;
3462
3463                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3464                         status = NT_STATUS_OBJECT_NAME_INVALID;
3465                         goto out;
3466                 }
3467                 if (dirtype == 0) {
3468                         dirtype = FILE_ATTRIBUTE_NORMAL;
3469                 }
3470
3471                 if (strequal(fname_mask,"????????.???")) {
3472                         TALLOC_FREE(fname_mask);
3473                         fname_mask = talloc_strdup(ctx, "*");
3474                         if (!fname_mask) {
3475                                 status = NT_STATUS_NO_MEMORY;
3476                                 goto out;
3477                         }
3478                 }
3479
3480                 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3481                                         fname_dir,
3482                                         NULL,
3483                                         NULL,
3484                                         smb_fname->twrp,
3485                                         smb_fname->flags);
3486                 if (smb_fname_dir == NULL) {
3487                         status = NT_STATUS_NO_MEMORY;
3488                         goto out;
3489                 }
3490
3491                 status = check_name(conn, smb_fname_dir);
3492                 if (!NT_STATUS_IS_OK(status)) {
3493                         goto out;
3494                 }
3495
3496                 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3497                                   dirtype);
3498                 if (dir_hnd == NULL) {
3499                         status = map_nt_error_from_unix(errno);
3500                         goto out;
3501                 }
3502
3503                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3504                    the pattern matches against the long name, otherwise the short name 
3505                    We don't implement this yet XXXX
3506                 */
3507
3508                 status = NT_STATUS_NO_SUCH_FILE;
3509
3510                 while ((dname = ReadDirName(dir_hnd, &offset,
3511                                             &smb_fname->st, &talloced))) {
3512                         TALLOC_CTX *frame = talloc_stackframe();
3513                         char *p = NULL;
3514                         struct smb_filename *f = NULL;
3515
3516                         if (!is_visible_file(conn,
3517                                         dir_hnd,
3518                                         dname,
3519                                         &smb_fname->st,
3520                                         true)) {
3521                                 TALLOC_FREE(frame);
3522                                 TALLOC_FREE(talloced);
3523                                 continue;
3524                         }
3525
3526                         /* Quick check for "." and ".." */
3527                         if (ISDOT(dname) || ISDOTDOT(dname)) {
3528                                 TALLOC_FREE(frame);
3529                                 TALLOC_FREE(talloced);
3530                                 continue;
3531                         }
3532
3533                         if(!mask_match(dname, fname_mask,
3534                                        conn->case_sensitive)) {
3535                                 TALLOC_FREE(frame);
3536                                 TALLOC_FREE(talloced);
3537                                 continue;
3538                         }
3539
3540                         if (ISDOT(fname_dir)) {
3541                                 /* Ensure we use canonical names on open. */
3542                                 p = talloc_asprintf(smb_fname, "%s", dname);
3543                         } else {
3544                                 p = talloc_asprintf(smb_fname, "%s/%s",
3545                                                     fname_dir, dname);
3546                         }
3547                         if (p == NULL) {
3548                                 TALLOC_FREE(dir_hnd);
3549                                 status = NT_STATUS_NO_MEMORY;
3550                                 TALLOC_FREE(frame);
3551                                 TALLOC_FREE(talloced);
3552                                 goto out;
3553                         }
3554                         f = synthetic_smb_fname(frame,
3555                                                 p,
3556                                                 NULL,
3557                                                 &smb_fname->st,
3558                                                 smb_fname->flags,
3559                                                 smb_fname->twrp);
3560                         if (f == NULL) {
3561                                 TALLOC_FREE(dir_hnd);
3562                                 status = NT_STATUS_NO_MEMORY;
3563                                 TALLOC_FREE(frame);
3564                                 TALLOC_FREE(talloced);
3565                                 goto out;
3566                         }
3567
3568                         status = check_name(conn, f);
3569                         if (!NT_STATUS_IS_OK(status)) {
3570                                 TALLOC_FREE(dir_hnd);
3571                                 TALLOC_FREE(frame);
3572                                 TALLOC_FREE(talloced);
3573                                 goto out;
3574                         }
3575
3576                         status = do_unlink(conn, req, f, dirtype);
3577                         if (!NT_STATUS_IS_OK(status)) {
3578                                 TALLOC_FREE(dir_hnd);
3579                                 TALLOC_FREE(frame);
3580                                 TALLOC_FREE(talloced);
3581                                 goto out;
3582                         }
3583
3584                         count++;
3585                         DBG_DEBUG("successful unlink [%s]\n",
3586                                   smb_fname_str_dbg(f));
3587
3588                         TALLOC_FREE(frame);
3589                         TALLOC_FREE(talloced);
3590                 }
3591                 TALLOC_FREE(dir_hnd);
3592         }
3593
3594         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3595                 status = map_nt_error_from_unix(errno);
3596         }
3597
3598  out:
3599         TALLOC_FREE(smb_fname_dir);
3600         TALLOC_FREE(fname_dir);
3601         TALLOC_FREE(fname_mask);
3602         return status;
3603 }
3604
3605 /****************************************************************************
3606  Reply to a unlink
3607 ****************************************************************************/
3608
3609 void reply_unlink(struct smb_request *req)
3610 {
3611         connection_struct *conn = req->conn;
3612         char *name = NULL;
3613         struct smb_filename *smb_fname = NULL;
3614         uint32_t dirtype;
3615         NTSTATUS status;
3616         bool path_contains_wcard = False;
3617         uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3618                         ucf_flags_from_smb_request(req);
3619         TALLOC_CTX *ctx = talloc_tos();
3620
3621         START_PROFILE(SMBunlink);
3622
3623         if (req->wct < 1) {
3624                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3625                 goto out;
3626         }
3627
3628         dirtype = SVAL(req->vwv+0, 0);
3629
3630         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3631                                   STR_TERMINATE, &status,
3632                                   &path_contains_wcard);
3633         if (!NT_STATUS_IS_OK(status)) {
3634                 reply_nterror(req, status);
3635                 goto out;
3636         }
3637
3638         status = filename_convert(ctx, conn,
3639                                   name,
3640                                   ucf_flags,
3641                                   0,
3642                                   &path_contains_wcard,
3643                                   &smb_fname);
3644         if (!NT_STATUS_IS_OK(status)) {
3645                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3646                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3647                                         ERRSRV, ERRbadpath);
3648                         goto out;
3649                 }
3650                 reply_nterror(req, status);
3651                 goto out;
3652         }
3653
3654         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3655
3656         status = unlink_internals(conn, req, dirtype, smb_fname);
3657         if (!NT_STATUS_IS_OK(status)) {
3658                 if (open_was_deferred(req->xconn, req->mid)) {
3659                         /* We have re-scheduled this call. */
3660                         goto out;
3661                 }
3662                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3663                         bool ok = defer_smb1_sharing_violation(req);
3664                         if (ok) {
3665                                 goto out;
3666                         }
3667                 }
3668                 reply_nterror(req, status);
3669                 goto out;
3670         }
3671
3672         reply_outbuf(req, 0, 0);
3673  out:
3674         TALLOC_FREE(smb_fname);
3675         END_PROFILE(SMBunlink);
3676         return;
3677 }
3678
3679 /****************************************************************************
3680  Fail for readbraw.
3681 ****************************************************************************/
3682
3683 static void fail_readraw(void)
3684 {
3685         const char *errstr = talloc_asprintf(talloc_tos(),
3686                         "FAIL ! reply_readbraw: socket write fail (%s)",
3687                         strerror(errno));
3688         if (!errstr) {
3689                 errstr = "";
3690         }
3691         exit_server_cleanly(errstr);
3692 }
3693
3694 /****************************************************************************
3695  Fake (read/write) sendfile. Returns -1 on read or write fail.
3696 ****************************************************************************/
3697
3698 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3699                       off_t startpos, size_t nread)
3700 {
3701         size_t bufsize;
3702         size_t tosend = nread;
3703         char *buf;
3704
3705         if (nread == 0) {
3706                 return 0;
3707         }
3708
3709         bufsize = MIN(nread, 65536);
3710
3711         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3712                 return -1;
3713         }
3714
3715         while (tosend > 0) {
3716                 ssize_t ret;
3717                 size_t cur_read;
3718
3719                 cur_read = MIN(tosend, bufsize);
3720                 ret = read_file(fsp,buf,startpos,cur_read);
3721                 if (ret == -1) {
3722                         SAFE_FREE(buf);
3723                         return -1;
3724                 }
3725
3726                 /* If we had a short read, fill with zeros. */
3727                 if (ret < cur_read) {
3728                         memset(buf + ret, '\0', cur_read - ret);
3729                 }
3730
3731                 ret = write_data(xconn->transport.sock, buf, cur_read);
3732                 if (ret != cur_read) {
3733                         int saved_errno = errno;
3734                         /*
3735                          * Try and give an error message saying what
3736                          * client failed.
3737                          */
3738                         DEBUG(0, ("write_data failed for client %s. "
3739                                   "Error %s\n",
3740                                   smbXsrv_connection_dbg(xconn),
3741                                   strerror(saved_errno)));
3742                         SAFE_FREE(buf);
3743                         errno = saved_errno;
3744                         return -1;
3745                 }
3746                 tosend -= cur_read;
3747                 startpos += cur_read;
3748         }
3749
3750         SAFE_FREE(buf);
3751         return (ssize_t)nread;
3752 }
3753
3754 /****************************************************************************
3755  Deal with the case of sendfile reading less bytes from the file than
3756  requested. Fill with zeros (all we can do). Returns 0 on success
3757 ****************************************************************************/
3758
3759 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3760                             files_struct *fsp,
3761                             ssize_t nread,
3762                             size_t headersize,
3763                             size_t smb_maxcnt)
3764 {
3765 #define SHORT_SEND_BUFSIZE 1024
3766         if (nread < headersize) {
3767                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3768                         "header for file %s (%s). Terminating\n",
3769                         fsp_str_dbg(fsp), strerror(errno)));
3770                 return -1;
3771         }
3772
3773         nread -= headersize;
3774
3775         if (nread < smb_maxcnt) {
3776                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3777                 if (!buf) {
3778                         DEBUG(0,("sendfile_short_send: malloc failed "
3779                                 "for file %s (%s). Terminating\n",
3780                                 fsp_str_dbg(fsp), strerror(errno)));
3781                         return -1;
3782                 }
3783
3784                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3785                         "with zeros !\n", fsp_str_dbg(fsp)));
3786
3787                 while (nread < smb_maxcnt) {
3788                         /*
3789                          * We asked for the real file size and told sendfile
3790                          * to not go beyond the end of the file. But it can
3791                          * happen that in between our fstat call and the
3792                          * sendfile call the file was truncated. This is very
3793                          * bad because we have already announced the larger
3794                          * number of bytes to the client.
3795                          *
3796                          * The best we can do now is to send 0-bytes, just as
3797                          * a read from a hole in a sparse file would do.
3798                          *
3799                          * This should happen rarely enough that I don't care
3800                          * about efficiency here :-)
3801                          */
3802                         size_t to_write;
3803                         ssize_t ret;
3804
3805                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3806                         ret = write_data(xconn->transport.sock, buf, to_write);
3807                         if (ret != to_write) {
3808                                 int saved_errno = errno;
3809                                 /*
3810                                  * Try and give an error message saying what
3811                                  * client failed.
3812                                  */
3813                                 DEBUG(0, ("write_data failed for client %s. "
3814                                           "Error %s\n",
3815                                           smbXsrv_connection_dbg(xconn),
3816                                           strerror(saved_errno)));
3817                                 errno = saved_errno;
3818                                 return -1;
3819                         }
3820                         nread += to_write;
3821                 }
3822                 SAFE_FREE(buf);
3823         }
3824
3825         return 0;
3826 }
3827
3828 /****************************************************************************
3829  Return a readbraw error (4 bytes of zero).
3830 ****************************************************************************/
3831
3832 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3833 {
3834         char header[4];
3835
3836         SIVAL(header,0,0);
3837
3838         smbd_lock_socket(xconn);
3839         if (write_data(xconn->transport.sock,header,4) != 4) {
3840                 int saved_errno = errno;
3841                 /*
3842                  * Try and give an error message saying what
3843                  * client failed.
3844                  */
3845                 DEBUG(0, ("write_data failed for client %s. "
3846                           "Error %s\n",
3847                           smbXsrv_connection_dbg(xconn),
3848                           strerror(saved_errno)));
3849                 errno = saved_errno;
3850
3851                 fail_readraw();
3852         }
3853         smbd_unlock_socket(xconn);
3854 }
3855
3856 /*******************************************************************
3857  Ensure we don't use sendfile if server smb signing is active.
3858 ********************************************************************/
3859
3860 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3861 {
3862         bool sign_active = false;
3863
3864         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3865         if (get_Protocol() < PROTOCOL_NT1) {
3866                 return false;
3867         }
3868         if (signing_state) {
3869                 sign_active = smb_signing_is_active(signing_state);
3870         }
3871         return (lp__use_sendfile(snum) &&
3872                         (get_remote_arch() != RA_WIN95) &&
3873                         !sign_active);
3874 }
3875 /****************************************************************************
3876  Use sendfile in readbraw.
3877 ****************************************************************************/
3878
3879 static void send_file_readbraw(connection_struct *conn,
3880                                struct smb_request *req,
3881                                files_struct *fsp,
3882                                off_t startpos,
3883                                size_t nread,
3884                                ssize_t mincount)
3885 {
3886         struct smbXsrv_connection *xconn = req->xconn;
3887         char *outbuf = NULL;
3888         ssize_t ret=0;
3889
3890         /*
3891          * We can only use sendfile on a non-chained packet 
3892          * but we can use on a non-oplocked file. tridge proved this
3893          * on a train in Germany :-). JRA.
3894          * reply_readbraw has already checked the length.
3895          */
3896
3897         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3898             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3899                 ssize_t sendfile_read = -1;
3900                 char header[4];
3901                 DATA_BLOB header_blob;
3902
3903                 _smb_setlen(header,nread);
3904                 header_blob = data_blob_const(header, 4);
3905
3906                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3907                                                  &header_blob, startpos,
3908                                                  nread);
3909                 if (sendfile_read == -1) {
3910                         /* Returning ENOSYS means no data at all was sent.
3911                          * Do this as a normal read. */
3912                         if (errno == ENOSYS) {
3913                                 goto normal_readbraw;
3914                         }
3915
3916                         /*
3917                          * Special hack for broken Linux with no working sendfile. If we
3918                          * return EINTR we sent the header but not the rest of the data.
3919                          * Fake this up by doing read/write calls.
3920                          */
3921                         if (errno == EINTR) {
3922                                 /* Ensure we don't do this again. */
3923                                 set_use_sendfile(SNUM(conn), False);
3924                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3925
3926                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3927                                         DEBUG(0,("send_file_readbraw: "
3928                                                  "fake_sendfile failed for "
3929                                                  "file %s (%s).\n",
3930                                                  fsp_str_dbg(fsp),
3931                                                  strerror(errno)));
3932                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3933                                 }
3934                                 return;
3935                         }
3936
3937                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3938                                  "file %s (%s). Terminating\n",
3939                                  fsp_str_dbg(fsp), strerror(errno)));
3940                         exit_server_cleanly("send_file_readbraw sendfile failed");
3941                 } else if (sendfile_read == 0) {
3942                         /*
3943                          * Some sendfile implementations return 0 to indicate
3944                          * that there was a short read, but nothing was
3945                          * actually written to the socket.  In this case,
3946                          * fallback to the normal read path so the header gets
3947                          * the correct byte count.
3948                          */
3949                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3950                                   "bytes falling back to the normal read: "
3951                                   "%s\n", fsp_str_dbg(fsp)));
3952                         goto normal_readbraw;
3953                 }
3954
3955                 /* Deal with possible short send. */
3956                 if (sendfile_read != 4+nread) {
3957                         ret = sendfile_short_send(xconn, fsp,
3958                                                   sendfile_read, 4, nread);
3959                         if (ret == -1) {
3960                                 fail_readraw();
3961                         }
3962                 }
3963                 return;
3964         }
3965
3966 normal_readbraw:
3967
3968         outbuf = talloc_array(NULL, char, nread+4);
3969         if (!outbuf) {
3970                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3971                         (unsigned)(nread+4)));
3972                 reply_readbraw_error(xconn);
3973                 return;
3974         }
3975
3976         if (nread > 0) {
3977                 ret = read_file(fsp,outbuf+4,startpos,nread);
3978 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3979                 if (ret < mincount)
3980                         ret = 0;
3981 #else
3982                 if (ret < nread)
3983                         ret = 0;
3984 #endif
3985         }
3986
3987         _smb_setlen(outbuf,ret);
3988         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3989                 int saved_errno = errno;
3990                 /*
3991                  * Try and give an error message saying what
3992                  * client failed.
3993                  */
3994                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3995                           smbXsrv_connection_dbg(xconn),
3996                           strerror(saved_errno)));
3997                 errno = saved_errno;
3998
3999                 fail_readraw();
4000         }
4001
4002         TALLOC_FREE(outbuf);
4003 }
4004
4005 /****************************************************************************
4006  Reply to a readbraw (core+ protocol).
4007 ****************************************************************************/
4008
4009 void reply_readbraw(struct smb_request *req)
4010 {
4011         connection_struct *conn = req->conn;
4012         struct smbXsrv_connection *xconn = req->xconn;
4013         ssize_t maxcount,mincount;
4014         size_t nread = 0;
4015         off_t startpos;
4016         files_struct *fsp;
4017         struct lock_struct lock;
4018         off_t size = 0;
4019         NTSTATUS status;
4020
4021         START_PROFILE(SMBreadbraw);
4022
4023         if (srv_is_signing_active(xconn) || req->encrypted) {
4024                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
4025                         "raw reads/writes are disallowed.");
4026         }
4027
4028         if (req->wct < 8) {
4029                 reply_readbraw_error(xconn);
4030                 END_PROFILE(SMBreadbraw);
4031                 return;
4032         }
4033
4034         if (xconn->smb1.echo_handler.trusted_fde) {
4035                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
4036                          "'async smb echo handler = yes'\n"));
4037                 reply_readbraw_error(xconn);
4038                 END_PROFILE(SMBreadbraw);
4039                 return;
4040         }
4041
4042         /*
4043          * Special check if an oplock break has been issued
4044          * and the readraw request croses on the wire, we must
4045          * return a zero length response here.
4046          */
4047
4048         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4049
4050         /*
4051          * We have to do a check_fsp by hand here, as
4052          * we must always return 4 zero bytes on error,
4053          * not a NTSTATUS.
4054          */
4055
4056         if (fsp == NULL ||
4057             conn == NULL ||
4058             conn != fsp->conn ||
4059             req->vuid != fsp->vuid ||
4060             fsp->fsp_flags.is_directory ||
4061             fsp->fh->fd == -1)
4062         {
4063                 /*
4064                  * fsp could be NULL here so use the value from the packet. JRA.
4065                  */
4066                 DEBUG(3,("reply_readbraw: fnum %d not valid "
4067                         "- cache prime?\n",
4068                         (int)SVAL(req->vwv+0, 0)));
4069                 reply_readbraw_error(xconn);
4070                 END_PROFILE(SMBreadbraw);
4071                 return;
4072         }
4073
4074         /* Do a "by hand" version of CHECK_READ. */
4075         if (!(fsp->fsp_flags.can_read ||
4076                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4077                                 (fsp->access_mask & FILE_EXECUTE)))) {
4078                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4079                                 (int)SVAL(req->vwv+0, 0)));
4080                 reply_readbraw_error(xconn);
4081                 END_PROFILE(SMBreadbraw);
4082                 return;
4083         }
4084
4085         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4086         if(req->wct == 10) {
4087                 /*
4088                  * This is a large offset (64 bit) read.
4089                  */
4090
4091                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4092
4093                 if(startpos < 0) {
4094                         DEBUG(0,("reply_readbraw: negative 64 bit "
4095                                 "readraw offset (%.0f) !\n",
4096                                 (double)startpos ));
4097                         reply_readbraw_error(xconn);
4098                         END_PROFILE(SMBreadbraw);
4099                         return;
4100                 }
4101         }
4102
4103         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4104         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4105
4106         /* ensure we don't overrun the packet size */
4107         maxcount = MIN(65535,maxcount);
4108
4109         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4110             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4111             &lock);
4112
4113         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4114                 reply_readbraw_error(xconn);
4115                 END_PROFILE(SMBreadbraw);
4116                 return;
4117         }
4118
4119         status = vfs_stat_fsp(fsp);
4120         if (NT_STATUS_IS_OK(status)) {
4121                 size = fsp->fsp_name->st.st_ex_size;
4122         }
4123
4124         if (startpos >= size) {
4125                 nread = 0;
4126         } else {
4127                 nread = MIN(maxcount,(size - startpos));
4128         }
4129
4130 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4131         if (nread < mincount)
4132                 nread = 0;
4133 #endif
4134
4135         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4136                 "min=%lu nread=%lu\n",
4137                 fsp_fnum_dbg(fsp), (double)startpos,
4138                 (unsigned long)maxcount,
4139                 (unsigned long)mincount,
4140                 (unsigned long)nread ) );
4141
4142         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4143
4144         DEBUG(5,("reply_readbraw finished\n"));
4145
4146         END_PROFILE(SMBreadbraw);
4147         return;
4148 }
4149
4150 #undef DBGC_CLASS
4151 #define DBGC_CLASS DBGC_LOCKING
4152
4153 /****************************************************************************
4154  Reply to a lockread (core+ protocol).
4155 ****************************************************************************/
4156
4157 static void reply_lockread_locked(struct tevent_req *subreq);
4158
4159 void reply_lockread(struct smb_request *req)
4160 {
4161         struct tevent_req *subreq = NULL;
4162         connection_struct *conn = req->conn;
4163         files_struct *fsp;
4164         struct smbd_lock_element *lck = NULL;
4165
4166         START_PROFILE(SMBlockread);
4167
4168         if (req->wct < 5) {
4169                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4170                 END_PROFILE(SMBlockread);
4171                 return;
4172         }
4173
4174         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4175
4176         if (!check_fsp(conn, req, fsp)) {
4177                 END_PROFILE(SMBlockread);
4178                 return;
4179         }
4180
4181         if (!CHECK_READ(fsp,req)) {
4182                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4183                 END_PROFILE(SMBlockread);
4184                 return;
4185         }
4186
4187         lck = talloc(req, struct smbd_lock_element);
4188         if (lck == NULL) {
4189                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4190                 END_PROFILE(SMBlockread);
4191                 return;
4192         }
4193
4194         /*
4195          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4196          * protocol request that predates the read/write lock concept. 
4197          * Thus instead of asking for a read lock here we need to ask
4198          * for a write lock. JRA.
4199          * Note that the requested lock size is unaffected by max_send.
4200          */
4201
4202         *lck = (struct smbd_lock_element) {
4203                 .req_guid = smbd_request_guid(req, 0),
4204                 .smblctx = req->smbpid,
4205                 .brltype = WRITE_LOCK,
4206                 .count = SVAL(req->vwv+1, 0),
4207                 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4208         };
4209
4210         subreq = smbd_smb1_do_locks_send(
4211                 fsp,
4212                 req->sconn->ev_ctx,
4213                 &req,
4214                 fsp,
4215                 0,
4216                 false,          /* large_offset */
4217                 WINDOWS_LOCK,
4218                 1,
4219                 lck);
4220         if (subreq == NULL) {
4221                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222                 END_PROFILE(SMBlockread);
4223                 return;
4224         }
4225         tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4226         END_PROFILE(SMBlockread);
4227 }
4228
4229 static void reply_lockread_locked(struct tevent_req *subreq)
4230 {
4231         struct smb_request *req = NULL;
4232         ssize_t nread = -1;
4233         char *data = NULL;
4234         NTSTATUS status;
4235         bool ok;
4236         off_t startpos;
4237         size_t numtoread, maxtoread;
4238         struct files_struct *fsp = NULL;
4239         char *p = NULL;
4240
4241         START_PROFILE(SMBlockread);
4242
4243         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4244         SMB_ASSERT(ok);
4245
4246         status = smbd_smb1_do_locks_recv(subreq);
4247         TALLOC_FREE(subreq);
4248
4249         if (!NT_STATUS_IS_OK(status)) {
4250                 reply_nterror(req, status);
4251                 goto send;
4252         }
4253
4254         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4255         if (fsp == NULL) {
4256                 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4257                 goto send;
4258         }
4259
4260         numtoread = SVAL(req->vwv+1, 0);
4261         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4262
4263         /*
4264          * However the requested READ size IS affected by max_send. Insanity.... JRA.
4265          */
4266         maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4267
4268         if (numtoread > maxtoread) {
4269                 DBG_WARNING("requested read size (%zu) is greater than "
4270                             "maximum allowed (%zu/%d). "
4271                             "Returning short read of maximum allowed for "
4272                             "compatibility with Windows 2000.\n",
4273                             numtoread,
4274                             maxtoread,
4275                             req->xconn->smb1.sessions.max_send);
4276                 numtoread = maxtoread;
4277         }
4278
4279         reply_outbuf(req, 5, numtoread + 3);
4280
4281         data = smb_buf(req->outbuf) + 3;
4282
4283         nread = read_file(fsp,data,startpos,numtoread);
4284
4285         if (nread < 0) {
4286                 reply_nterror(req, map_nt_error_from_unix(errno));
4287                 goto send;
4288         }
4289
4290         srv_set_message((char *)req->outbuf, 5, nread+3, False);
4291
4292         SSVAL(req->outbuf,smb_vwv0,nread);
4293         SSVAL(req->outbuf,smb_vwv5,nread+3);
4294         p = smb_buf(req->outbuf);
4295         SCVAL(p,0,0); /* pad byte. */
4296         SSVAL(p,1,nread);
4297
4298         DEBUG(3,("lockread %s num=%d nread=%d\n",
4299                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4300
4301 send:
4302         ok = srv_send_smb(req->xconn,
4303                           (char *)req->outbuf,
4304                           true,
4305                           req->seqnum+1,
4306                           IS_CONN_ENCRYPTED(req->conn),
4307                           NULL);
4308         if (!ok) {
4309                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4310         }
4311         TALLOC_FREE(req);
4312         END_PROFILE(SMBlockread);
4313         return;
4314 }
4315
4316 #undef DBGC_CLASS
4317 #define DBGC_CLASS DBGC_ALL
4318
4319 /****************************************************************************
4320  Reply to a read.
4321 ****************************************************************************/
4322
4323 void reply_read(struct smb_request *req)
4324 {
4325         connection_struct *conn = req->conn;
4326         size_t numtoread;
4327         size_t maxtoread;
4328         ssize_t nread = 0;
4329         char *data;
4330         off_t startpos;
4331         files_struct *fsp;
4332         struct lock_struct lock;
4333         struct smbXsrv_connection *xconn = req->xconn;
4334
4335         START_PROFILE(SMBread);
4336
4337         if (req->wct < 3) {
4338                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4339                 END_PROFILE(SMBread);
4340                 return;
4341         }
4342
4343         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4344
4345         if (!check_fsp(conn, req, fsp)) {
4346                 END_PROFILE(SMBread);
4347                 return;
4348         }
4349
4350         if (!CHECK_READ(fsp,req)) {
4351                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4352                 END_PROFILE(SMBread);
4353                 return;
4354         }
4355
4356         numtoread = SVAL(req->vwv+1, 0);
4357         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4358
4359         /*
4360          * The requested read size cannot be greater than max_send. JRA.
4361          */
4362         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4363
4364         if (numtoread > maxtoread) {
4365                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4366 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4367                         (unsigned int)numtoread, (unsigned int)maxtoread,
4368                         (unsigned int)xconn->smb1.sessions.max_send));
4369                 numtoread = maxtoread;
4370         }
4371
4372         reply_outbuf(req, 5, numtoread+3);
4373
4374         data = smb_buf(req->outbuf) + 3;
4375
4376         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4377             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4378             &lock);
4379
4380         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4381                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4382                 END_PROFILE(SMBread);
4383                 return;
4384         }
4385
4386         if (numtoread > 0)
4387                 nread = read_file(fsp,data,startpos,numtoread);
4388
4389         if (nread < 0) {
4390                 reply_nterror(req, map_nt_error_from_unix(errno));
4391                 goto out;
4392         }
4393
4394         srv_set_message((char *)req->outbuf, 5, nread+3, False);
4395
4396         SSVAL(req->outbuf,smb_vwv0,nread);
4397         SSVAL(req->outbuf,smb_vwv5,nread+3);
4398         SCVAL(smb_buf(req->outbuf),0,1);
4399         SSVAL(smb_buf(req->outbuf),1,nread);
4400
4401         DEBUG(3, ("read %s num=%d nread=%d\n",
4402                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4403
4404 out:
4405         END_PROFILE(SMBread);
4406         return;
4407 }
4408
4409 /****************************************************************************
4410  Setup readX header.
4411 ****************************************************************************/
4412
4413 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4414 {
4415         size_t outsize;
4416
4417         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4418                                   False);
4419
4420         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4421
4422         SCVAL(outbuf,smb_vwv0,0xFF);
4423         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4424         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4425         SSVAL(outbuf,smb_vwv6,
4426               (smb_wct - 4)     /* offset from smb header to wct */
4427               + 1               /* the wct field */
4428               + 12 * sizeof(uint16_t) /* vwv */
4429               + 2               /* the buflen field */
4430               + 1);             /* padding byte */
4431         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4432         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4433         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4434         _smb_setlen_large(outbuf,
4435                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4436         return outsize;
4437 }
4438
4439 /****************************************************************************
4440  Reply to a read and X - possibly using sendfile.
4441 ****************************************************************************/
4442
4443 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4444                             files_struct *fsp, off_t startpos,
4445                             size_t smb_maxcnt)
4446 {
4447         struct smbXsrv_connection *xconn = req->xconn;
4448         ssize_t nread = -1;
4449         struct lock_struct lock;
4450         int saved_errno = 0;
4451         NTSTATUS status;
4452
4453         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4454             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4455             &lock);
4456
4457         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4458                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4459                 return;
4460         }
4461
4462         /*
4463          * We can only use sendfile on a non-chained packet
4464          * but we can use on a non-oplocked file. tridge proved this
4465          * on a train in Germany :-). JRA.
4466          */
4467
4468         if (!req_is_in_chain(req) &&
4469             !req->encrypted &&
4470             (fsp->base_fsp == NULL) &&
4471             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4472                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4473                 DATA_BLOB header;
4474
4475                 status = vfs_stat_fsp(fsp);
4476                 if (!NT_STATUS_IS_OK(status)) {
4477                         reply_nterror(req, status);
4478                         goto out;
4479                 }
4480
4481                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4482                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4483                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4484                         /*
4485                          * We already know that we would do a short read, so don't
4486                          * try the sendfile() path.
4487                          */
4488                         goto nosendfile_read;
4489                 }
4490
4491                 /*
4492                  * Set up the packet header before send. We
4493                  * assume here the sendfile will work (get the
4494                  * correct amount of data).
4495                  */
4496
4497                 header = data_blob_const(headerbuf, sizeof(headerbuf));
4498
4499                 construct_reply_common_req(req, (char *)headerbuf);
4500                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4501
4502                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4503                                          startpos, smb_maxcnt);
4504                 if (nread == -1) {
4505                         saved_errno = errno;
4506
4507                         /* Returning ENOSYS means no data at all was sent.
4508                            Do this as a normal read. */
4509                         if (errno == ENOSYS) {
4510                                 goto normal_read;
4511                         }
4512
4513                         /*
4514                          * Special hack for broken Linux with no working sendfile. If we
4515                          * return EINTR we sent the header but not the rest of the data.
4516                          * Fake this up by doing read/write calls.
4517                          */
4518
4519                         if (errno == EINTR) {
4520                                 /* Ensure we don't do this again. */
4521                                 set_use_sendfile(SNUM(conn), False);
4522                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4523                                 nread = fake_sendfile(xconn, fsp, startpos,
4524                                                       smb_maxcnt);
4525                                 if (nread == -1) {
4526                                         saved_errno = errno;
4527                                         DEBUG(0,("send_file_readX: "
4528                                                  "fake_sendfile failed for "
4529                                                  "file %s (%s) for client %s. "
4530                                                  "Terminating\n",
4531                                                  fsp_str_dbg(fsp),
4532                                                  smbXsrv_connection_dbg(xconn),
4533                                                  strerror(saved_errno)));
4534                                         errno = saved_errno;
4535                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4536                                 }
4537                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4538                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4539                                 /* No outbuf here means successful sendfile. */
4540                                 goto out;
4541                         }
4542
4543                         DEBUG(0,("send_file_readX: sendfile failed for file "
4544                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4545                                  strerror(errno)));
4546                         exit_server_cleanly("send_file_readX sendfile failed");
4547                 } else if (nread == 0) {
4548                         /*
4549                          * Some sendfile implementations return 0 to indicate
4550                          * that there was a short read, but nothing was
4551                          * actually written to the socket.  In this case,
4552                          * fallback to the normal read path so the header gets
4553                          * the correct byte count.
4554                          */
4555                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4556                                   "falling back to the normal read: %s\n",
4557                                   fsp_str_dbg(fsp)));
4558                         goto normal_read;
4559                 }
4560
4561                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4562                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4563
4564                 /* Deal with possible short send. */
4565                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4566                         ssize_t ret;
4567
4568                         ret = sendfile_short_send(xconn, fsp, nread,
4569                                                   sizeof(headerbuf), smb_maxcnt);
4570                         if (ret == -1) {
4571                                 const char *r;
4572                                 r = "send_file_readX: sendfile_short_send failed";
4573                                 DEBUG(0,("%s for file %s (%s).\n",
4574                                          r, fsp_str_dbg(fsp), strerror(errno)));
4575                                 exit_server_cleanly(r);
4576                         }
4577                 }
4578                 /* No outbuf here means successful sendfile. */
4579                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4580                 SMB_PERFCOUNT_END(&req->pcd);
4581                 goto out;
4582         }
4583
4584 normal_read:
4585
4586         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4587                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4588                 ssize_t ret;
4589
4590                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4591                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4592                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4593                         /*
4594                          * We already know that we would do a short
4595                          * read, so don't try the sendfile() path.
4596                          */
4597                         goto nosendfile_read;
4598                 }
4599
4600                 construct_reply_common_req(req, (char *)headerbuf);
4601                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4602
4603                 /* Send out the header. */
4604                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4605                                  sizeof(headerbuf));
4606                 if (ret != sizeof(headerbuf)) {
4607                         saved_errno = errno;
4608                         /*
4609                          * Try and give an error message saying what
4610                          * client failed.
4611                          */
4612                         DEBUG(0,("send_file_readX: write_data failed for file "
4613                                  "%s (%s) for client %s. Terminating\n",
4614                                  fsp_str_dbg(fsp),
4615                                  smbXsrv_connection_dbg(xconn),
4616                                  strerror(saved_errno)));
4617                         errno = saved_errno;
4618                         exit_server_cleanly("send_file_readX sendfile failed");
4619                 }
4620                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4621                 if (nread == -1) {
4622                         saved_errno = errno;
4623                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4624                                  "%s (%s) for client %s. Terminating\n",
4625                                  fsp_str_dbg(fsp),
4626                                  smbXsrv_connection_dbg(xconn),
4627                                  strerror(saved_errno)));
4628                         errno = saved_errno;
4629                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4630                 }
4631                 goto out;
4632         }
4633
4634 nosendfile_read:
4635
4636         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4637         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4638         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4639
4640         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4641                           startpos, smb_maxcnt);
4642         saved_errno = errno;
4643
4644         if (nread < 0) {
4645                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4646                 return;
4647         }
4648
4649         setup_readX_header((char *)req->outbuf, nread);
4650
4651         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4652                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4653         return;
4654
4655 out:
4656         TALLOC_FREE(req->outbuf);
4657         return;
4658 }
4659
4660 /****************************************************************************
4661  Work out how much space we have for a read return.
4662 ****************************************************************************/
4663
4664 static size_t calc_max_read_pdu(const struct smb_request *req)
4665 {
4666         struct smbXsrv_connection *xconn = req->xconn;
4667
4668         if (xconn->protocol < PROTOCOL_NT1) {
4669                 return xconn->smb1.sessions.max_send;
4670         }
4671
4672         if (!lp_large_readwrite()) {
4673                 return xconn->smb1.sessions.max_send;
4674         }
4675
4676         if (req_is_in_chain(req)) {
4677                 return xconn->smb1.sessions.max_send;
4678         }
4679
4680         if (req->encrypted) {
4681                 /*
4682                  * Don't take encrypted traffic up to the
4683                  * limit. There are padding considerations
4684                  * that make that tricky.
4685                  */
4686                 return xconn->smb1.sessions.max_send;
4687         }
4688
4689         if (srv_is_signing_active(xconn)) {
4690                 return 0x1FFFF;
4691         }
4692
4693         if (!lp_unix_extensions()) {
4694                 return 0x1FFFF;
4695         }
4696
4697         /*
4698          * We can do ultra-large POSIX reads.
4699          */
4700         return 0xFFFFFF;
4701 }
4702
4703 /****************************************************************************
4704  Calculate how big a read can be. Copes with all clients. It's always
4705  safe to return a short read - Windows does this.
4706 ****************************************************************************/
4707
4708 static size_t calc_read_size(const struct smb_request *req,
4709                              size_t upper_size,
4710                              size_t lower_size)
4711 {
4712         struct smbXsrv_connection *xconn = req->xconn;
4713         size_t max_pdu = calc_max_read_pdu(req);
4714         size_t total_size = 0;
4715         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4716         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4717
4718         /*
4719          * Windows explicitly ignores upper size of 0xFFFF.
4720          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4721          * We must do the same as these will never fit even in
4722          * an extended size NetBIOS packet.
4723          */
4724         if (upper_size == 0xFFFF) {
4725                 upper_size = 0;
4726         }
4727
4728         if (xconn->protocol < PROTOCOL_NT1) {
4729                 upper_size = 0;
4730         }
4731
4732         total_size = ((upper_size<<16) | lower_size);
4733
4734         /*
4735          * LARGE_READX test shows it's always safe to return
4736          * a short read. Windows does so.
4737          */
4738         return MIN(total_size, max_len);
4739 }
4740
4741 /****************************************************************************
4742  Reply to a read and X.
4743 ****************************************************************************/
4744
4745 void reply_read_and_X(struct smb_request *req)
4746 {
4747         connection_struct *conn = req->conn;
4748         files_struct *fsp;
4749         off_t startpos;
4750         size_t smb_maxcnt;
4751         size_t upper_size;
4752         bool big_readX = False;
4753 #if 0
4754         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4755 #endif
4756
4757         START_PROFILE(SMBreadX);
4758
4759         if ((req->wct != 10) && (req->wct != 12)) {
4760                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4761                 return;
4762         }
4763
4764         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4765         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4766         smb_maxcnt = SVAL(req->vwv+5, 0);
4767
4768         /* If it's an IPC, pass off the pipe handler. */
4769         if (IS_IPC(conn)) {
4770                 reply_pipe_read_and_X(req);
4771                 END_PROFILE(SMBreadX);
4772                 return;
4773         }
4774
4775         if (!check_fsp(conn, req, fsp)) {
4776                 END_PROFILE(SMBreadX);
4777                 return;
4778         }
4779
4780         if (!CHECK_READ(fsp,req)) {
4781                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4782                 END_PROFILE(SMBreadX);
4783                 return;
4784         }
4785
4786         upper_size = SVAL(req->vwv+7, 0);
4787         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4788         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4789                 /*
4790                  * This is a heuristic to avoid keeping large
4791                  * outgoing buffers around over long-lived aio
4792                  * requests.
4793                  */
4794                 big_readX = True;
4795         }
4796
4797         if (req->wct == 12) {
4798                 /*
4799                  * This is a large offset (64 bit) read.
4800                  */
4801                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4802
4803         }
4804
4805         if (!big_readX) {
4806                 NTSTATUS status = schedule_aio_read_and_X(conn,
4807                                         req,
4808                                         fsp,
4809                                         startpos,
4810                                         smb_maxcnt);
4811                 if (NT_STATUS_IS_OK(status)) {
4812                         /* Read scheduled - we're done. */
4813                         goto out;
4814                 }
4815                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4816                         /* Real error - report to client. */
4817                         END_PROFILE(SMBreadX);
4818                         reply_nterror(req, status);
4819                         return;
4820                 }
4821                 /* NT_STATUS_RETRY - fall back to sync read. */
4822         }
4823
4824         smbd_lock_socket(req->xconn);
4825         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4826         smbd_unlock_socket(req->xconn);
4827
4828  out:
4829         END_PROFILE(SMBreadX);
4830         return;
4831 }
4832
4833 /****************************************************************************
4834  Error replies to writebraw must have smb_wct == 1. Fix this up.
4835 ****************************************************************************/
4836
4837 void error_to_writebrawerr(struct smb_request *req)
4838 {
4839         uint8_t *old_outbuf = req->outbuf;
4840
4841         reply_outbuf(req, 1, 0);
4842
4843         memcpy(req->outbuf, old_outbuf, smb_size);
4844         TALLOC_FREE(old_outbuf);
4845 }
4846
4847 /****************************************************************************
4848  Read 4 bytes of a smb packet and return the smb length of the packet.
4849  Store the result in the buffer. This version of the function will
4850  never return a session keepalive (length of zero).
4851  Timeout is in milliseconds.
4852 ****************************************************************************/
4853
4854 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4855                                 size_t *len)
4856 {
4857         uint8_t msgtype = NBSSkeepalive;
4858
4859         while (msgtype == NBSSkeepalive) {
4860                 NTSTATUS status;
4861
4862                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4863                                                           len);
4864                 if (!NT_STATUS_IS_OK(status)) {
4865                         char addr[INET6_ADDRSTRLEN];
4866                         /* Try and give an error message
4867                          * saying what client failed. */
4868                         DEBUG(0, ("read_smb_length_return_keepalive failed for "
4869                                   "client %s read error = %s.\n",
4870                                   get_peer_addr(fd,addr,sizeof(addr)),
4871                                   nt_errstr(status)));
4872                         return status;
4873                 }
4874
4875                 msgtype = CVAL(inbuf, 0);
4876         }
4877
4878         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4879                   (unsigned long)len));
4880
4881         return NT_STATUS_OK;
4882 }
4883
4884 /****************************************************************************
4885  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4886 ****************************************************************************/
4887
4888 void reply_writebraw(struct smb_request *req)
4889 {
4890         connection_struct *conn = req->conn;
4891         struct smbXsrv_connection *xconn = req->xconn;
4892         char *buf = NULL;
4893         ssize_t nwritten=0;
4894         ssize_t total_written=0;
4895         size_t numtowrite=0;
4896         size_t tcount;
4897         off_t startpos;
4898         const char *data=NULL;
4899         bool write_through;
4900         files_struct *fsp;
4901         struct lock_struct lock;
4902         NTSTATUS status;
4903
4904         START_PROFILE(SMBwritebraw);
4905
4906         /*
4907          * If we ever reply with an error, it must have the SMB command
4908          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4909          * we're finished.
4910          */
4911         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4912
4913         if (srv_is_signing_active(xconn)) {
4914                 END_PROFILE(SMBwritebraw);
4915                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4916                                 "raw reads/writes are disallowed.");
4917         }
4918
4919         if (req->wct < 12) {
4920                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4921                 error_to_writebrawerr(req);
4922                 END_PROFILE(SMBwritebraw);
4923                 return;
4924         }
4925
4926         if (xconn->smb1.echo_handler.trusted_fde) {
4927                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4928                          "'async smb echo handler = yes'\n"));
4929                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4930                 error_to_writebrawerr(req);
4931                 END_PROFILE(SMBwritebraw);
4932                 return;
4933         }
4934
4935         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4936         if (!check_fsp(conn, req, fsp)) {
4937                 error_to_writebrawerr(req);
4938                 END_PROFILE(SMBwritebraw);
4939                 return;
4940         }
4941
4942         if (!CHECK_WRITE(fsp)) {
4943                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4944                 error_to_writebrawerr(req);
4945                 END_PROFILE(SMBwritebraw);
4946                 return;
4947         }
4948
4949         tcount = IVAL(req->vwv+1, 0);
4950         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4951         write_through = BITSETW(req->vwv+7,0);
4952
4953         /* We have to deal with slightly different formats depending
4954                 on whether we are using the core+ or lanman1.0 protocol */
4955
4956         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4957                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4958                 data = smb_buf_const(req->inbuf);
4959         } else {
4960                 numtowrite = SVAL(req->vwv+10, 0);
4961                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4962         }
4963
4964         /* Ensure we don't write bytes past the end of this packet. */
4965         /*
4966          * This already protects us against CVE-2017-12163.
4967          */
4968         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4969                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4970                 error_to_writebrawerr(req);
4971                 END_PROFILE(SMBwritebraw);
4972                 return;
4973         }
4974
4975         if (!fsp->print_file) {
4976                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4977                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4978                     &lock);
4979
4980                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4981                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4982                         error_to_writebrawerr(req);
4983                         END_PROFILE(SMBwritebraw);
4984                         return;
4985                 }
4986         }
4987
4988         if (numtowrite>0) {
4989                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4990         }
4991
4992         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4993                         "wrote=%d sync=%d\n",
4994                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4995                 (int)nwritten, (int)write_through));
4996
4997         if (nwritten < (ssize_t)numtowrite)  {
4998                 reply_nterror(req, NT_STATUS_DISK_FULL);
4999                 error_to_writebrawerr(req);
5000                 goto out;
5001         }
5002
5003         total_written = nwritten;
5004
5005         /* Allocate a buffer of 64k + length. */
5006         buf = talloc_array(NULL, char, 65540);
5007         if (!buf) {
5008                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5009                 error_to_writebrawerr(req);
5010                 goto out;
5011         }
5012
5013         /* Return a SMBwritebraw message to the redirector to tell
5014          * it to send more bytes */
5015
5016         memcpy(buf, req->inbuf, smb_size);
5017         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
5018         SCVAL(buf,smb_com,SMBwritebraw);
5019         SSVALS(buf,smb_vwv0,0xFFFF);
5020         show_msg(buf);
5021         if (!srv_send_smb(req->xconn,
5022                           buf,
5023                           false, 0, /* no signing */
5024                           IS_CONN_ENCRYPTED(conn),
5025                           &req->pcd)) {
5026                 exit_server_cleanly("reply_writebraw: srv_send_smb "
5027                         "failed.");
5028         }
5029
5030         /* Now read the raw data into the buffer and write it */
5031         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
5032                                  &numtowrite);
5033         if (!NT_STATUS_IS_OK(status)) {
5034                 exit_server_cleanly("secondary writebraw failed");
5035         }
5036
5037         /* Set up outbuf to return the correct size */
5038         reply_outbuf(req, 1, 0);
5039
5040         if (numtowrite != 0) {
5041
5042                 if (numtowrite > 0xFFFF) {
5043                         DEBUG(0,("reply_writebraw: Oversize secondary write "
5044                                 "raw requested (%u). Terminating\n",
5045                                 (unsigned int)numtowrite ));
5046                         exit_server_cleanly("secondary writebraw failed");
5047                 }
5048
5049                 if (tcount > nwritten+numtowrite) {
5050                         DEBUG(3,("reply_writebraw: Client overestimated the "
5051                                 "write %d %d %d\n",
5052                                 (int)tcount,(int)nwritten,(int)numtowrite));
5053                 }
5054
5055                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5056                                             numtowrite);
5057
5058                 if (!NT_STATUS_IS_OK(status)) {
5059                         /* Try and give an error message
5060                          * saying what client failed. */
5061                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
5062                                   "raw read failed (%s) for client %s. "
5063                                   "Terminating\n", nt_errstr(status),
5064                                   smbXsrv_connection_dbg(xconn)));
5065                         exit_server_cleanly("secondary writebraw failed");
5066                 }
5067
5068                 /*
5069                  * We are not vulnerable to CVE-2017-12163
5070                  * here as we are guaranteed to have numtowrite
5071                  * bytes available - we just read from the client.
5072                  */
5073                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5074                 if (nwritten == -1) {
5075                         TALLOC_FREE(buf);
5076                         reply_nterror(req, map_nt_error_from_unix(errno));
5077                         error_to_writebrawerr(req);
5078                         goto out;
5079                 }
5080
5081                 if (nwritten < (ssize_t)numtowrite) {
5082                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
5083                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
5084                 }
5085
5086                 if (nwritten > 0) {
5087                         total_written += nwritten;
5088                 }
5089         }
5090
5091         TALLOC_FREE(buf);
5092         SSVAL(req->outbuf,smb_vwv0,total_written);
5093
5094         status = sync_file(conn, fsp, write_through);
5095         if (!NT_STATUS_IS_OK(status)) {
5096                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5097                          fsp_str_dbg(fsp), nt_errstr(status)));
5098                 reply_nterror(req, status);
5099                 error_to_writebrawerr(req);
5100                 goto out;
5101         }
5102
5103         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5104                 "wrote=%d\n",
5105                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5106                 (int)total_written));
5107
5108         /* We won't return a status if write through is not selected - this
5109          * follows what WfWg does */
5110         END_PROFILE(SMBwritebraw);
5111
5112         if (!write_through && total_written==tcount) {
5113
5114 #if RABBIT_PELLET_FIX
5115                 /*
5116                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5117                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5118                  * JRA.
5119                  */
5120                 if (!send_keepalive(xconn->transport.sock)) {
5121                         exit_server_cleanly("reply_writebraw: send of "
5122                                 "keepalive failed");
5123                 }
5124 #endif
5125                 TALLOC_FREE(req->outbuf);
5126         }
5127         return;
5128
5129 out:
5130         END_PROFILE(SMBwritebraw);
5131         return;
5132 }
5133
5134 #undef DBGC_CLASS
5135 #define DBGC_CLASS DBGC_LOCKING
5136
5137 /****************************************************************************
5138  Reply to a writeunlock (core+).
5139 ****************************************************************************/
5140
5141 void reply_writeunlock(struct smb_request *req)
5142 {
5143         connection_struct *conn = req->conn;
5144         ssize_t nwritten = -1;
5145         size_t numtowrite;
5146         size_t remaining;
5147         off_t startpos;
5148         const char *data;
5149         NTSTATUS status = NT_STATUS_OK;
5150         files_struct *fsp;
5151         struct lock_struct lock;
5152         int saved_errno = 0;
5153
5154         START_PROFILE(SMBwriteunlock);
5155
5156         if (req->wct < 5) {
5157                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5158                 END_PROFILE(SMBwriteunlock);
5159                 return;
5160         }
5161
5162         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5163
5164         if (!check_fsp(conn, req, fsp)) {
5165                 END_PROFILE(SMBwriteunlock);
5166                 return;
5167         }
5168
5169         if (!CHECK_WRITE(fsp)) {
5170                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5171                 END_PROFILE(SMBwriteunlock);
5172                 return;
5173         }
5174
5175         numtowrite = SVAL(req->vwv+1, 0);
5176         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5177         data = (const char *)req->buf + 3;
5178
5179         /*
5180          * Ensure client isn't asking us to write more than
5181          * they sent. CVE-2017-12163.
5182          */
5183         remaining = smbreq_bufrem(req, data);
5184         if (numtowrite > remaining) {
5185                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5186                 END_PROFILE(SMBwriteunlock);
5187                 return;
5188         }
5189
5190         if (!fsp->print_file && numtowrite > 0) {
5191                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5192                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5193                     &lock);
5194
5195                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5196                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5197                         END_PROFILE(SMBwriteunlock);
5198                         return;
5199                 }
5200         }
5201
5202         /* The special X/Open SMB protocol handling of
5203            zero length writes is *NOT* done for
5204            this call */
5205         if(numtowrite == 0) {
5206                 nwritten = 0;
5207         } else {
5208                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5209                 saved_errno = errno;
5210         }
5211
5212         status = sync_file(conn, fsp, False /* write through */);
5213         if (!NT_STATUS_IS_OK(status)) {
5214                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5215                          fsp_str_dbg(fsp), nt_errstr(status)));
5216                 reply_nterror(req, status);
5217                 goto out;
5218         }
5219
5220         if(nwritten < 0) {
5221                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5222                 goto out;
5223         }
5224
5225         if((nwritten < numtowrite) && (numtowrite != 0)) {
5226                 reply_nterror(req, NT_STATUS_DISK_FULL);
5227                 goto out;
5228         }
5229
5230         if (numtowrite && !fsp->print_file) {
5231                 struct smbd_lock_element l = {
5232                         .req_guid = smbd_request_guid(req, 0),
5233                         .smblctx = req->smbpid,
5234                         .brltype = UNLOCK_LOCK,
5235                         .offset = startpos,
5236                         .count = numtowrite,
5237                 };
5238                 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5239                 if (NT_STATUS_V(status)) {
5240                         reply_nterror(req, status);
5241                         goto out;
5242                 }
5243         }
5244
5245         reply_outbuf(req, 1, 0);
5246
5247         SSVAL(req->outbuf,smb_vwv0,nwritten);
5248
5249         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5250                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5251
5252 out:
5253         END_PROFILE(SMBwriteunlock);
5254         return;
5255 }
5256
5257 #undef DBGC_CLASS
5258 #define DBGC_CLASS DBGC_ALL
5259
5260 /****************************************************************************
5261  Reply to a write.
5262 ****************************************************************************/
5263
5264 void reply_write(struct smb_request *req)
5265 {
5266         connection_struct *conn = req->conn;
5267         size_t numtowrite;
5268         size_t remaining;
5269         ssize_t nwritten = -1;
5270         off_t startpos;
5271         const char *data;
5272         files_struct *fsp;
5273         struct lock_struct lock;
5274         NTSTATUS status;
5275         int saved_errno = 0;
5276
5277         START_PROFILE(SMBwrite);
5278
5279         if (req->wct < 5) {
5280                 END_PROFILE(SMBwrite);
5281                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5282                 return;
5283         }
5284
5285         /* If it's an IPC, pass off the pipe handler. */
5286         if (IS_IPC(conn)) {
5287                 reply_pipe_write(req);
5288                 END_PROFILE(SMBwrite);
5289                 return;
5290         }
5291
5292         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5293
5294         if (!check_fsp(conn, req, fsp)) {
5295                 END_PROFILE(SMBwrite);
5296                 return;
5297         }
5298
5299         if (!CHECK_WRITE(fsp)) {
5300                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5301                 END_PROFILE(SMBwrite);
5302                 return;
5303         }
5304
5305         numtowrite = SVAL(req->vwv+1, 0);
5306         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5307         data = (const char *)req->buf + 3;
5308
5309         /*
5310          * Ensure client isn't asking us to write more than
5311          * they sent. CVE-2017-12163.
5312          */
5313         remaining = smbreq_bufrem(req, data);
5314         if (numtowrite > remaining) {
5315                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5316                 END_PROFILE(SMBwrite);
5317                 return;
5318         }
5319
5320         if (!fsp->print_file) {
5321                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5322                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5323                         &lock);
5324
5325                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5326                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5327                         END_PROFILE(SMBwrite);
5328                         return;
5329                 }
5330         }
5331
5332         /*
5333          * X/Open SMB protocol says that if smb_vwv1 is
5334          * zero then the file size should be extended or
5335          * truncated to the size given in smb_vwv[2-3].
5336          */
5337
5338         if(numtowrite == 0) {
5339                 /*
5340                  * This is actually an allocate call, and set EOF. JRA.
5341                  */
5342                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5343                 if (nwritten < 0) {
5344                         reply_nterror(req, NT_STATUS_DISK_FULL);
5345                         goto out;
5346                 }
5347                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5348                 if (nwritten < 0) {
5349                         reply_nterror(req, NT_STATUS_DISK_FULL);
5350                         goto out;
5351                 }
5352                 trigger_write_time_update_immediate(fsp);
5353         } else {
5354                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5355         }
5356
5357         status = sync_file(conn, fsp, False);
5358         if (!NT_STATUS_IS_OK(status)) {
5359                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5360                          fsp_str_dbg(fsp), nt_errstr(status)));
5361                 reply_nterror(req, status);
5362                 goto out;
5363         }
5364
5365         if(nwritten < 0) {
5366                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5367                 goto out;
5368         }
5369
5370         if((nwritten == 0) && (numtowrite != 0)) {
5371                 reply_nterror(req, NT_STATUS_DISK_FULL);
5372                 goto out;
5373         }
5374
5375         reply_outbuf(req, 1, 0);
5376
5377         SSVAL(req->outbuf,smb_vwv0,nwritten);
5378
5379         if (nwritten < (ssize_t)numtowrite) {
5380                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5381                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5382         }
5383
5384         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5385
5386 out:
5387         END_PROFILE(SMBwrite);
5388         return;
5389 }
5390
5391 /****************************************************************************
5392  Ensure a buffer is a valid writeX for recvfile purposes.
5393 ****************************************************************************/
5394
5395 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5396                                                 (2*14) + /* word count (including bcc) */ \
5397                                                 1 /* pad byte */)
5398
5399 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5400                             const uint8_t *inbuf)
5401 {
5402         size_t numtowrite;
5403         unsigned int doff = 0;
5404         size_t len = smb_len_large(inbuf);
5405         uint16_t fnum;
5406         struct smbXsrv_open *op = NULL;
5407         struct files_struct *fsp = NULL;
5408         NTSTATUS status;
5409
5410         if (is_encrypted_packet(inbuf)) {
5411                 /* Can't do this on encrypted
5412                  * connections. */
5413                 return false;
5414         }
5415
5416         if (CVAL(inbuf,smb_com) != SMBwriteX) {
5417                 return false;
5418         }
5419
5420         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5421                         CVAL(inbuf,smb_wct) != 14) {
5422                 DEBUG(10,("is_valid_writeX_buffer: chained or "
5423                         "invalid word length.\n"));
5424                 return false;
5425         }
5426
5427         fnum = SVAL(inbuf, smb_vwv2);
5428         status = smb1srv_open_lookup(xconn,
5429                                      fnum,
5430                                      0, /* now */
5431                                      &op);
5432         if (!NT_STATUS_IS_OK(status)) {
5433                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5434                 return false;
5435         }
5436         fsp = op->compat;
5437         if (fsp == NULL) {
5438                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5439                 return false;
5440         }
5441         if (fsp->conn == NULL) {
5442                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5443                 return false;
5444         }
5445
5446         if (IS_IPC(fsp->conn)) {
5447                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5448                 return false;
5449         }
5450         if (IS_PRINT(fsp->conn)) {
5451                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5452                 return false;
5453         }
5454         if (fsp->base_fsp != NULL) {
5455                 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5456                 return false;
5457         }
5458         doff = SVAL(inbuf,smb_vwv11);
5459
5460         numtowrite = SVAL(inbuf,smb_vwv10);
5461
5462         if (len > doff && len - doff > 0xFFFF) {
5463                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5464         }
5465
5466         if (numtowrite == 0) {
5467                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5468                 return false;
5469         }
5470
5471         /* Ensure the sizes match up. */
5472         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5473                 /* no pad byte...old smbclient :-( */
5474                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5475                         (unsigned int)doff,
5476                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5477                 return false;
5478         }
5479
5480         if (len - doff != numtowrite) {
5481                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5482                         "len = %u, doff = %u, numtowrite = %u\n",
5483                         (unsigned int)len,
5484                         (unsigned int)doff,
5485                         (unsigned int)numtowrite ));
5486                 return false;
5487         }
5488
5489         DEBUG(10,("is_valid_writeX_buffer: true "
5490                 "len = %u, doff = %u, numtowrite = %u\n",
5491                 (unsigned int)len,
5492                 (unsigned int)doff,
5493                 (unsigned int)numtowrite ));
5494
5495         return true;
5496 }
5497
5498 /****************************************************************************
5499  Reply to a write and X.
5500 ****************************************************************************/
5501
5502 void reply_write_and_X(struct smb_request *req)
5503 {
5504         connection_struct *conn = req->conn;
5505         struct smbXsrv_connection *xconn = req->xconn;
5506         files_struct *fsp;
5507         struct lock_struct lock;
5508         off_t startpos;
5509         size_t numtowrite;
5510         bool write_through;
5511         ssize_t nwritten;
5512         unsigned int smb_doff;
5513         unsigned int smblen;
5514         const char *data;
5515         NTSTATUS status;
5516         int saved_errno = 0;
5517
5518         START_PROFILE(SMBwriteX);
5519
5520         if ((req->wct != 12) && (req->wct != 14)) {
5521                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5522                 goto out;
5523         }
5524
5525         numtowrite = SVAL(req->vwv+10, 0);
5526         smb_doff = SVAL(req->vwv+11, 0);
5527         smblen = smb_len(req->inbuf);
5528
5529         if (req->unread_bytes > 0xFFFF ||
5530                         (smblen > smb_doff &&
5531                                 smblen - smb_doff > 0xFFFF)) {
5532                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5533         }
5534
5535         if (req->unread_bytes) {
5536                 /* Can't do a recvfile write on IPC$ */
5537                 if (IS_IPC(conn)) {
5538                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5539                         goto out;
5540                 }
5541                 if (numtowrite != req->unread_bytes) {
5542                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5543                         goto out;
5544                 }
5545         } else {
5546                 /*
5547                  * This already protects us against CVE-2017-12163.
5548                  */
5549                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5550                                 smb_doff + numtowrite > smblen) {
5551                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5552                         goto out;
5553                 }
5554         }
5555
5556         /* If it's an IPC, pass off the pipe handler. */
5557         if (IS_IPC(conn)) {
5558                 if (req->unread_bytes) {
5559                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5560                         goto out;
5561                 }
5562                 reply_pipe_write_and_X(req);
5563                 goto out;
5564         }
5565
5566         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5567         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5568         write_through = BITSETW(req->vwv+7,0);
5569
5570         if (!check_fsp(conn, req, fsp)) {
5571                 goto out;
5572         }
5573
5574         if (!CHECK_WRITE(fsp)) {
5575                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5576                 goto out;
5577         }
5578
5579         data = smb_base(req->inbuf) + smb_doff;
5580
5581         if(req->wct == 14) {
5582                 /*
5583                  * This is a large offset (64 bit) write.
5584                  */
5585                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5586
5587         }
5588
5589         /* X/Open SMB protocol says that, unlike SMBwrite
5590         if the length is zero then NO truncation is
5591         done, just a write of zero. To truncate a file,
5592         use SMBwrite. */
5593
5594         if(numtowrite == 0) {
5595                 nwritten = 0;
5596         } else {
5597                 if (req->unread_bytes == 0) {
5598                         status = schedule_aio_write_and_X(conn,
5599                                                 req,
5600                                                 fsp,
5601                                                 data,
5602                                                 startpos,
5603                                                 numtowrite);
5604
5605                         if (NT_STATUS_IS_OK(status)) {
5606                                 /* write scheduled - we're done. */
5607                                 goto out;
5608                         }
5609                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5610                                 /* Real error - report to client. */
5611                                 reply_nterror(req, status);
5612                                 goto out;
5613                         }
5614                         /* NT_STATUS_RETRY - fall through to sync write. */
5615                 }
5616
5617                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5618                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5619                     &lock);
5620
5621                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5622                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5623                         goto out;
5624                 }
5625
5626                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5627                 saved_errno = errno;
5628         }
5629
5630         if(nwritten < 0) {
5631                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5632                 goto out;
5633         }
5634
5635         if((nwritten == 0) && (numtowrite != 0)) {
5636                 reply_nterror(req, NT_STATUS_DISK_FULL);
5637                 goto out;
5638         }
5639
5640         reply_outbuf(req, 6, 0);
5641         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5642         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
5643         SSVAL(req->outbuf,smb_vwv2,nwritten);
5644         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5645
5646         DEBUG(3,("writeX %s num=%d wrote=%d\n",
5647                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5648
5649         status = sync_file(conn, fsp, write_through);
5650         if (!NT_STATUS_IS_OK(status)) {
5651                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5652                          fsp_str_dbg(fsp), nt_errstr(status)));
5653                 reply_nterror(req, status);
5654                 goto out;
5655         }
5656
5657         END_PROFILE(SMBwriteX);
5658         return;
5659
5660 out:
5661         if (req->unread_bytes) {
5662                 /* writeX failed. drain socket. */
5663                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5664                                 req->unread_bytes) {
5665                         smb_panic("failed to drain pending bytes");
5666                 }
5667                 req->unread_bytes = 0;
5668         }
5669
5670         END_PROFILE(SMBwriteX);
5671         return;
5672 }
5673
5674 /****************************************************************************
5675  Reply to a lseek.
5676 ****************************************************************************/
5677
5678 void reply_lseek(struct smb_request *req)
5679 {
5680         connection_struct *conn = req->conn;
5681         off_t startpos;
5682         off_t res= -1;
5683         int mode,umode;
5684         files_struct *fsp;
5685         NTSTATUS status;
5686
5687         START_PROFILE(SMBlseek);
5688
5689         if (req->wct < 4) {
5690                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5691                 END_PROFILE(SMBlseek);
5692                 return;
5693         }
5694
5695         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5696
5697         if (!check_fsp(conn, req, fsp)) {
5698                 return;
5699         }
5700
5701         mode = SVAL(req->vwv+1, 0) & 3;
5702         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5703         startpos = (off_t)IVALS(req->vwv+2, 0);
5704
5705         switch (mode) {
5706                 case 0:
5707                         umode = SEEK_SET;
5708                         res = startpos;
5709                         break;
5710                 case 1:
5711                         umode = SEEK_CUR;
5712                         res = fsp->fh->pos + startpos;
5713                         break;
5714                 case 2:
5715                         umode = SEEK_END;
5716                         break;
5717                 default:
5718                         umode = SEEK_SET;
5719                         res = startpos;
5720                         break;
5721         }
5722
5723         if (umode == SEEK_END) {
5724                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5725                         if(errno == EINVAL) {
5726                                 off_t current_pos = startpos;
5727
5728                                 status = vfs_stat_fsp(fsp);
5729                                 if (!NT_STATUS_IS_OK(status)) {
5730                                         reply_nterror(req, status);
5731                                         END_PROFILE(SMBlseek);
5732                                         return;
5733                                 }
5734
5735                                 current_pos += fsp->fsp_name->st.st_ex_size;
5736                                 if(current_pos < 0)
5737                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5738                         }
5739                 }
5740
5741                 if(res == -1) {
5742                         reply_nterror(req, map_nt_error_from_unix(errno));
5743                         END_PROFILE(SMBlseek);
5744                         return;
5745                 }
5746         }
5747
5748         fsp->fh->pos = res;
5749
5750         reply_outbuf(req, 2, 0);
5751         SIVAL(req->outbuf,smb_vwv0,res);
5752
5753         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5754                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5755
5756         END_PROFILE(SMBlseek);
5757         return;
5758 }
5759
5760 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5761                                              void *private_data)
5762 {
5763         connection_struct *conn = talloc_get_type_abort(
5764                 private_data, connection_struct);
5765
5766         if (conn != fsp->conn) {
5767                 return NULL;
5768         }
5769         if (fsp->fh->fd == -1) {
5770                 return NULL;
5771         }
5772         sync_file(conn, fsp, True /* write through */);
5773
5774         if (fsp->fsp_flags.modified) {
5775                 trigger_write_time_update_immediate(fsp);
5776         }
5777
5778         return NULL;
5779 }
5780
5781 /****************************************************************************
5782  Reply to a flush.
5783 ****************************************************************************/
5784
5785 void reply_flush(struct smb_request *req)
5786 {
5787         connection_struct *conn = req->conn;
5788         uint16_t fnum;
5789         files_struct *fsp;
5790
5791         START_PROFILE(SMBflush);
5792
5793         if (req->wct < 1) {
5794                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5795                 return;
5796         }
5797
5798         fnum = SVAL(req->vwv+0, 0);
5799         fsp = file_fsp(req, fnum);
5800
5801         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5802                 return;
5803         }
5804
5805         if (!fsp) {
5806                 files_forall(req->sconn, file_sync_one_fn, conn);
5807         } else {
5808                 NTSTATUS status = sync_file(conn, fsp, True);
5809                 if (!NT_STATUS_IS_OK(status)) {
5810                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5811                                 fsp_str_dbg(fsp), nt_errstr(status)));
5812                         reply_nterror(req, status);
5813                         END_PROFILE(SMBflush);
5814                         return;
5815                 }
5816                 if (fsp->fsp_flags.modified) {
5817                         trigger_write_time_update_immediate(fsp);
5818                 }
5819         }
5820
5821         reply_outbuf(req, 0, 0);
5822
5823         DEBUG(3,("flush\n"));
5824         END_PROFILE(SMBflush);
5825         return;
5826 }
5827
5828 /****************************************************************************
5829  Reply to a exit.
5830  conn POINTER CAN BE NULL HERE !
5831 ****************************************************************************/
5832
5833 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5834 static void reply_exit_done(struct tevent_req *req);
5835
5836 void reply_exit(struct smb_request *smb1req)
5837 {
5838         struct tevent_req *req;
5839
5840         /*
5841          * Don't setup the profile charge here, take
5842          * it in reply_exit_done(). Not strictly correct
5843          * but better than the other SMB1 async
5844          * code that double-charges at the moment.
5845          */
5846         req = reply_exit_send(smb1req);
5847         if (req == NULL) {
5848                 /* Not going async, profile here. */
5849                 START_PROFILE(SMBexit);
5850                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5851                 END_PROFILE(SMBexit);
5852                 return;
5853         }
5854
5855         /* We're async. This will complete later. */
5856         tevent_req_set_callback(req, reply_exit_done, smb1req);
5857         return;
5858 }
5859
5860 struct reply_exit_state {
5861         struct tevent_queue *wait_queue;
5862 };
5863
5864 static void reply_exit_wait_done(struct tevent_req *subreq);
5865
5866 /****************************************************************************
5867  Async SMB1 exit.
5868  Note, on failure here we deallocate and return NULL to allow the caller to
5869  SMB1 return an error of ERRnomem immediately.
5870 ****************************************************************************/
5871
5872 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5873 {
5874         struct tevent_req *req;
5875         struct reply_exit_state *state;
5876         struct tevent_req *subreq;
5877         files_struct *fsp;
5878         struct smbd_server_connection *sconn = smb1req->sconn;
5879
5880         req = tevent_req_create(smb1req, &state,
5881                         struct reply_exit_state);
5882         if (req == NULL) {
5883                 return NULL;
5884         }
5885         state->wait_queue = tevent_queue_create(state,
5886                                 "reply_exit_wait_queue");
5887         if (tevent_req_nomem(state->wait_queue, req)) {
5888                 TALLOC_FREE(req);
5889                 return NULL;
5890         }
5891
5892         for (fsp = sconn->files; fsp; fsp = fsp->next) {
5893                 if (fsp->file_pid != smb1req->smbpid) {
5894                         continue;
5895                 }
5896                 if (fsp->vuid != smb1req->vuid) {
5897                         continue;
5898                 }
5899                 /*
5900                  * Flag the file as close in progress.
5901                  * This will prevent any more IO being
5902                  * done on it.
5903                  */
5904                 fsp->fsp_flags.closing = true;
5905
5906                 if (fsp->num_aio_requests > 0) {
5907                         /*
5908                          * Now wait until all aio requests on this fsp are
5909                          * finished.
5910                          *
5911                          * We don't set a callback, as we just want to block the
5912                          * wait queue and the talloc_free() of fsp->aio_request
5913                          * will remove the item from the wait queue.
5914                          */
5915                         subreq = tevent_queue_wait_send(fsp->aio_requests,
5916                                                 sconn->ev_ctx,
5917                                                 state->wait_queue);
5918                         if (tevent_req_nomem(subreq, req)) {
5919                                 TALLOC_FREE(req);
5920                                 return NULL;
5921                         }
5922                 }
5923         }
5924
5925         /*
5926          * Now we add our own waiter to the end of the queue,
5927          * this way we get notified when all pending requests are finished
5928          * and reply to the outstanding SMB1 request.
5929          */
5930         subreq = tevent_queue_wait_send(state,
5931                                 sconn->ev_ctx,
5932                                 state->wait_queue);
5933         if (tevent_req_nomem(subreq, req)) {
5934                 TALLOC_FREE(req);
5935                 return NULL;
5936         }
5937
5938         /*
5939          * We're really going async - move the SMB1 request from
5940          * a talloc stackframe above us to the conn talloc-context.
5941          * We need this to stick around until the wait_done
5942          * callback is invoked.
5943          */
5944         smb1req = talloc_move(sconn, &smb1req);
5945
5946         tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5947
5948         return req;
5949 }
5950
5951 static void reply_exit_wait_done(struct tevent_req *subreq)
5952 {
5953         struct tevent_req *req = tevent_req_callback_data(
5954                 subreq, struct tevent_req);
5955
5956         tevent_queue_wait_recv(subreq);
5957         TALLOC_FREE(subreq);
5958         tevent_req_done(req);
5959 }
5960
5961 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5962 {
5963         return tevent_req_simple_recv_ntstatus(req);
5964 }
5965
5966 static void reply_exit_done(struct tevent_req *req)
5967 {
5968         struct smb_request *smb1req = tevent_req_callback_data(
5969                 req, struct smb_request);
5970         struct smbd_server_connection *sconn = smb1req->sconn;
5971         struct smbXsrv_connection *xconn = smb1req->xconn;
5972         NTTIME now = timeval_to_nttime(&smb1req->request_time);
5973         struct smbXsrv_session *session = NULL;
5974         files_struct *fsp, *next;
5975         NTSTATUS status;
5976
5977         /*
5978          * Take the profile charge here. Not strictly
5979          * correct but better than the other SMB1 async
5980          * code that double-charges at the moment.
5981          */
5982         START_PROFILE(SMBexit);
5983
5984         status = reply_exit_recv(req);
5985         TALLOC_FREE(req);
5986         if (!NT_STATUS_IS_OK(status)) {
5987                 TALLOC_FREE(smb1req);
5988                 END_PROFILE(SMBexit);
5989                 exit_server(__location__ ": reply_exit_recv failed");
5990                 return;
5991         }
5992
5993         /*
5994          * Ensure the session is still valid.
5995          */
5996         status = smb1srv_session_lookup(xconn,
5997                                         smb1req->vuid,
5998                                         now,
5999                                         &session);
6000         if (!NT_STATUS_IS_OK(status)) {
6001                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6002                 smb_request_done(smb1req);
6003                 END_PROFILE(SMBexit);
6004         }
6005
6006         /*
6007          * Ensure the vuid is still valid - no one
6008          * called reply_ulogoffX() in the meantime.
6009          * reply_exit() doesn't have AS_USER set, so
6010          * use set_current_user_info() directly.
6011          * This is the same logic as in switch_message().
6012          */
6013         if (session->global->auth_session_info != NULL) {
6014                 set_current_user_info(
6015                         session->global->auth_session_info->unix_info->sanitized_username,
6016                         session->global->auth_session_info->unix_info->unix_name,
6017                         session->global->auth_session_info->info->domain_name);
6018         }
6019
6020         /* No more aio - do the actual closes. */
6021         for (fsp = sconn->files; fsp; fsp = next) {
6022                 bool ok;
6023                 next = fsp->next;
6024
6025                 if (fsp->file_pid != smb1req->smbpid) {
6026                         continue;
6027                 }
6028                 if (fsp->vuid != smb1req->vuid) {
6029                         continue;
6030                 }
6031                 if (!fsp->fsp_flags.closing) {
6032                         continue;
6033                 }
6034
6035                 /*
6036                  * reply_exit() has the DO_CHDIR flag set.
6037                  */
6038                 ok = chdir_current_service(fsp->conn);
6039                 if (!ok) {
6040                         reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6041                         smb_request_done(smb1req);
6042                         END_PROFILE(SMBexit);
6043                 }
6044                 close_file(NULL, fsp, SHUTDOWN_CLOSE);
6045         }
6046
6047         reply_outbuf(smb1req, 0, 0);
6048         /*
6049          * The following call is needed to push the
6050          * reply data back out the socket after async
6051          * return. Plus it frees smb1req.
6052          */
6053         smb_request_done(smb1req);
6054         DBG_INFO("reply_exit complete\n");
6055         END_PROFILE(SMBexit);
6056         return;
6057 }
6058
6059 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6060                                 files_struct *fsp);
6061 static void reply_close_done(struct tevent_req *req);
6062
6063 void reply_close(struct smb_request *smb1req)
6064 {
6065         connection_struct *conn = smb1req->conn;
6066         NTSTATUS status = NT_STATUS_OK;
6067         files_struct *fsp = NULL;
6068         START_PROFILE(SMBclose);
6069
6070         if (smb1req->wct < 3) {
6071                 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6072                 END_PROFILE(SMBclose);
6073                 return;
6074         }
6075
6076         fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6077
6078         /*
6079          * We can only use check_fsp if we know it's not a directory.
6080          */
6081
6082         if (!check_fsp_open(conn, smb1req, fsp)) {
6083                 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6084                 END_PROFILE(SMBclose);
6085                 return;
6086         }
6087
6088         DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6089                   fsp->fsp_flags.is_directory ?
6090                   "directory" : "file",
6091                   fsp->fh->fd, fsp_fnum_dbg(fsp),
6092                   conn->num_files_open);
6093
6094         if (!fsp->fsp_flags.is_directory) {
6095                 time_t t;
6096
6097                 /*
6098                  * Take care of any time sent in the close.
6099                  */
6100
6101                 t = srv_make_unix_date3(smb1req->vwv+1);
6102                 set_close_write_time(fsp, time_t_to_full_timespec(t));
6103         }
6104
6105         if (fsp->num_aio_requests != 0) {
6106                 struct tevent_req *req;
6107
6108                 req = reply_close_send(smb1req, fsp);
6109                 if (req == NULL) {
6110                         status = NT_STATUS_NO_MEMORY;
6111                         goto done;
6112                 }
6113                 /* We're async. This will complete later. */
6114                 tevent_req_set_callback(req, reply_close_done, smb1req);
6115                 END_PROFILE(SMBclose);
6116                 return;
6117         }
6118
6119         /*
6120          * close_file() returns the unix errno if an error was detected on
6121          * close - normally this is due to a disk full error. If not then it
6122          * was probably an I/O error.
6123          */
6124
6125         status = close_file(smb1req, fsp, NORMAL_CLOSE);
6126 done:
6127         if (!NT_STATUS_IS_OK(status)) {
6128                 reply_nterror(smb1req, status);
6129                 END_PROFILE(SMBclose);
6130                 return;
6131         }
6132
6133         reply_outbuf(smb1req, 0, 0);
6134         END_PROFILE(SMBclose);
6135         return;
6136 }
6137
6138 struct reply_close_state {
6139         files_struct *fsp;
6140         struct tevent_queue *wait_queue;
6141 };
6142
6143 static void reply_close_wait_done(struct tevent_req *subreq);
6144
6145 /****************************************************************************
6146  Async SMB1 close.
6147  Note, on failure here we deallocate and return NULL to allow the caller to
6148  SMB1 return an error of ERRnomem immediately.
6149 ****************************************************************************/
6150
6151 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6152                                 files_struct *fsp)
6153 {
6154         struct tevent_req *req;
6155         struct reply_close_state *state;
6156         struct tevent_req *subreq;
6157         struct smbd_server_connection *sconn = smb1req->sconn;
6158
6159         req = tevent_req_create(smb1req, &state,
6160                         struct reply_close_state);
6161         if (req == NULL) {
6162                 return NULL;
6163         }
6164         state->wait_queue = tevent_queue_create(state,
6165                                 "reply_close_wait_queue");
6166         if (tevent_req_nomem(state->wait_queue, req)) {
6167                 TALLOC_FREE(req);
6168                 return NULL;
6169         }
6170
6171         /*
6172          * Flag the file as close in progress.
6173          * This will prevent any more IO being
6174          * done on it.
6175          */
6176         fsp->fsp_flags.closing = true;
6177
6178         /*
6179          * Now wait until all aio requests on this fsp are
6180          * finished.
6181          *
6182          * We don't set a callback, as we just want to block the
6183          * wait queue and the talloc_free() of fsp->aio_request
6184          * will remove the item from the wait queue.
6185          */
6186         subreq = tevent_queue_wait_send(fsp->aio_requests,
6187                                         sconn->ev_ctx,
6188                                         state->wait_queue);
6189         if (tevent_req_nomem(subreq, req)) {
6190                 TALLOC_FREE(req);
6191                 return NULL;
6192         }
6193
6194         /*
6195          * Now we add our own waiter to the end of the queue,
6196          * this way we get notified when all pending requests are finished
6197          * and reply to the outstanding SMB1 request.
6198          */
6199         subreq = tevent_queue_wait_send(state,
6200                                 sconn->ev_ctx,
6201                                 state->wait_queue);
6202         if (tevent_req_nomem(subreq, req)) {
6203                 TALLOC_FREE(req);
6204                 return NULL;
6205         }
6206
6207         /*
6208          * We're really going async - move the SMB1 request from
6209          * a talloc stackframe above us to the conn talloc-context.
6210          * We need this to stick around until the wait_done
6211          * callback is invoked.
6212          */
6213         smb1req = talloc_move(sconn, &smb1req);
6214
6215         tevent_req_set_callback(subreq, reply_close_wait_done, req);
6216
6217         return req;
6218 }
6219
6220 static void reply_close_wait_done(struct tevent_req *subreq)
6221 {
6222         struct tevent_req *req = tevent_req_callback_data(
6223                 subreq, struct tevent_req);
6224
6225         tevent_queue_wait_recv(subreq);
6226         TALLOC_FREE(subreq);
6227         tevent_req_done(req);
6228 }
6229
6230 static NTSTATUS reply_close_recv(struct tevent_req *req)
6231 {
6232         return tevent_req_simple_recv_ntstatus(req);
6233 }
6234
6235 static void reply_close_done(struct tevent_req *req)
6236 {
6237         struct smb_request *smb1req = tevent_req_callback_data(
6238                         req, struct smb_request);
6239         struct reply_close_state *state = tevent_req_data(req,
6240                                                 struct reply_close_state);
6241         NTSTATUS status;
6242
6243         status = reply_close_recv(req);
6244         TALLOC_FREE(req);
6245         if (!NT_STATUS_IS_OK(status)) {
6246                 TALLOC_FREE(smb1req);
6247                 exit_server(__location__ ": reply_close_recv failed");
6248                 return;
6249         }
6250
6251         status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6252         if (NT_STATUS_IS_OK(status)) {
6253                 reply_outbuf(smb1req, 0, 0);
6254         } else {
6255                 reply_nterror(smb1req, status);
6256         }
6257         /*
6258          * The following call is needed to push the
6259          * reply data back out the socket after async
6260          * return. Plus it frees smb1req.
6261          */
6262         smb_request_done(smb1req);
6263 }
6264
6265 /****************************************************************************
6266  Reply to a writeclose (Core+ protocol).
6267 ****************************************************************************/
6268
6269 void reply_writeclose(struct smb_request *req)
6270 {
6271         connection_struct *conn = req->conn;
6272         size_t numtowrite;
6273         size_t remaining;
6274         ssize_t nwritten = -1;
6275         NTSTATUS close_status = NT_STATUS_OK;
6276         off_t startpos;
6277         const char *data;
6278         struct timespec mtime;
6279         files_struct *fsp;
6280         struct lock_struct lock;
6281
6282         START_PROFILE(SMBwriteclose);
6283
6284         if (req->wct < 6) {
6285                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6286                 END_PROFILE(SMBwriteclose);
6287                 return;
6288         }
6289
6290         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6291
6292         if (!check_fsp(conn, req, fsp)) {
6293                 END_PROFILE(SMBwriteclose);
6294                 return;
6295         }
6296         if (!CHECK_WRITE(fsp)) {
6297                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6298                 END_PROFILE(SMBwriteclose);
6299                 return;
6300         }
6301
6302         numtowrite = SVAL(req->vwv+1, 0);
6303         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6304         mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6305         data = (const char *)req->buf + 1;
6306
6307         /*
6308          * Ensure client isn't asking us to write more than
6309          * they sent. CVE-2017-12163.
6310          */
6311         remaining = smbreq_bufrem(req, data);
6312         if (numtowrite > remaining) {
6313                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6314                 END_PROFILE(SMBwriteclose);
6315                 return;
6316         }
6317
6318         if (fsp->print_file == NULL) {
6319                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6320                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6321                     &lock);
6322
6323                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6324                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6325                         END_PROFILE(SMBwriteclose);
6326                         return;
6327                 }
6328         }
6329
6330         nwritten = write_file(req,fsp,data,startpos,numtowrite);
6331
6332         set_close_write_time(fsp, mtime);
6333
6334         /*
6335          * More insanity. W2K only closes the file if writelen > 0.
6336          * JRA.
6337          */
6338
6339         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6340                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6341                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6342
6343         if (numtowrite) {
6344                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6345                          "file %s\n", fsp_str_dbg(fsp)));
6346                 close_status = close_file(req, fsp, NORMAL_CLOSE);
6347                 fsp = NULL;
6348         }
6349
6350         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6351                 reply_nterror(req, NT_STATUS_DISK_FULL);
6352                 goto out;
6353         }
6354
6355         if(!NT_STATUS_IS_OK(close_status)) {
6356                 reply_nterror(req, close_status);
6357                 goto out;
6358         }
6359
6360         reply_outbuf(req, 1, 0);
6361
6362         SSVAL(req->outbuf,smb_vwv0,nwritten);
6363
6364 out:
6365
6366         END_PROFILE(SMBwriteclose);
6367         return;
6368 }
6369
6370 #undef DBGC_CLASS
6371 #define DBGC_CLASS DBGC_LOCKING
6372
6373 /****************************************************************************
6374  Reply to a lock.
6375 ****************************************************************************/
6376
6377 static void reply_lock_done(struct tevent_req *subreq);
6378
6379 void reply_lock(struct smb_request *req)
6380 {
6381         struct tevent_req *subreq = NULL;
6382         connection_struct *conn = req->conn;
6383         files_struct *fsp;
6384         struct smbd_lock_element *lck = NULL;
6385
6386         START_PROFILE(SMBlock);
6387
6388         if (req->wct < 5) {
6389                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6390                 END_PROFILE(SMBlock);
6391                 return;
6392         }
6393
6394         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6395
6396         if (!check_fsp(conn, req, fsp)) {
6397                 END_PROFILE(SMBlock);
6398                 return;
6399         }
6400
6401         lck = talloc(req, struct smbd_lock_element);
6402         if (lck == NULL) {
6403                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6404                 END_PROFILE(SMBlock);
6405                 return;
6406         }
6407
6408         *lck = (struct smbd_lock_element) {
6409                 .req_guid = smbd_request_guid(req, 0),
6410                 .smblctx = req->smbpid,
6411                 .brltype = WRITE_LOCK,
6412                 .count = IVAL(req->vwv+1, 0),
6413                 .offset = IVAL(req->vwv+3, 0),
6414         };
6415
6416         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6417                    fsp->fh->fd,
6418                    fsp_fnum_dbg(fsp),
6419                    lck->offset,
6420                    lck->count);
6421
6422         subreq = smbd_smb1_do_locks_send(
6423                 fsp,
6424                 req->sconn->ev_ctx,
6425                 &req,
6426                 fsp,
6427                 0,
6428                 false,          /* large_offset */
6429                 WINDOWS_LOCK,
6430                 1,
6431                 lck);
6432         if (subreq == NULL) {
6433                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6434                 END_PROFILE(SMBlock);
6435                 return;
6436         }
6437         tevent_req_set_callback(subreq, reply_lock_done, NULL);
6438         END_PROFILE(SMBlock);
6439 }
6440
6441 static void reply_lock_done(struct tevent_req *subreq)
6442 {
6443         struct smb_request *req = NULL;
6444         NTSTATUS status;
6445         bool ok;
6446
6447         START_PROFILE(SMBlock);
6448
6449         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6450         SMB_ASSERT(ok);
6451
6452         status = smbd_smb1_do_locks_recv(subreq);
6453         TALLOC_FREE(subreq);
6454
6455         if (NT_STATUS_IS_OK(status)) {
6456                 reply_outbuf(req, 0, 0);
6457         } else {
6458                 reply_nterror(req, status);
6459         }
6460
6461         ok = srv_send_smb(req->xconn,
6462                           (char *)req->outbuf,
6463                           true,
6464                           req->seqnum+1,
6465                           IS_CONN_ENCRYPTED(req->conn),
6466                           NULL);
6467         if (!ok) {
6468                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6469         }
6470         TALLOC_FREE(req);
6471         END_PROFILE(SMBlock);
6472 }
6473
6474 /****************************************************************************
6475  Reply to a unlock.
6476 ****************************************************************************/
6477
6478 void reply_unlock(struct smb_request *req)
6479 {
6480         connection_struct *conn = req->conn;
6481         NTSTATUS status;
6482         files_struct *fsp;
6483         struct smbd_lock_element lck;
6484
6485         START_PROFILE(SMBunlock);
6486
6487         if (req->wct < 5) {
6488                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6489                 END_PROFILE(SMBunlock);
6490                 return;
6491         }
6492
6493         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6494
6495         if (!check_fsp(conn, req, fsp)) {
6496                 END_PROFILE(SMBunlock);
6497                 return;
6498         }
6499
6500         lck = (struct smbd_lock_element) {
6501                 .req_guid = smbd_request_guid(req, 0),
6502                 .smblctx = req->smbpid,
6503                 .brltype = UNLOCK_LOCK,
6504                 .offset = IVAL(req->vwv+3, 0),
6505                 .count = IVAL(req->vwv+1, 0),
6506         };
6507
6508         status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6509
6510         if (!NT_STATUS_IS_OK(status)) {
6511                 reply_nterror(req, status);
6512                 END_PROFILE(SMBunlock);
6513                 return;
6514         }
6515
6516         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6517                    fsp->fh->fd,
6518                    fsp_fnum_dbg(fsp),
6519                    lck.offset,
6520                    lck.count);
6521
6522         reply_outbuf(req, 0, 0);
6523
6524         END_PROFILE(SMBunlock);
6525         return;
6526 }
6527
6528 #undef DBGC_CLASS
6529 #define DBGC_CLASS DBGC_ALL
6530
6531 /****************************************************************************
6532  Reply to a tdis.
6533  conn POINTER CAN BE NULL HERE !
6534 ****************************************************************************/
6535
6536 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6537 static void reply_tdis_done(struct tevent_req *req);
6538
6539 void reply_tdis(struct smb_request *smb1req)
6540 {
6541         connection_struct *conn = smb1req->conn;
6542         struct tevent_req *req;
6543
6544         /*
6545          * Don't setup the profile charge here, take
6546          * it in reply_tdis_done(). Not strictly correct
6547          * but better than the other SMB1 async
6548          * code that double-charges at the moment.
6549          */
6550
6551         if (conn == NULL) {
6552                 /* Not going async, profile here. */
6553                 START_PROFILE(SMBtdis);
6554                 DBG_INFO("Invalid connection in tdis\n");
6555                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6556                 END_PROFILE(SMBtdis);
6557                 return;
6558         }
6559
6560         req = reply_tdis_send(smb1req);
6561         if (req == NULL) {
6562                 /* Not going async, profile here. */
6563                 START_PROFILE(SMBtdis);
6564                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6565                 END_PROFILE(SMBtdis);
6566                 return;
6567         }
6568         /* We're async. This will complete later. */
6569         tevent_req_set_callback(req, reply_tdis_done, smb1req);
6570         return;
6571 }
6572
6573 struct reply_tdis_state {
6574         struct tevent_queue *wait_queue;
6575 };
6576
6577 static void reply_tdis_wait_done(struct tevent_req *subreq);
6578
6579 /****************************************************************************
6580  Async SMB1 tdis.
6581  Note, on failure here we deallocate and return NULL to allow the caller to
6582  SMB1 return an error of ERRnomem immediately.
6583 ****************************************************************************/
6584
6585 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6586 {
6587         struct tevent_req *req;
6588         struct reply_tdis_state *state;
6589         struct tevent_req *subreq;
6590         connection_struct *conn = smb1req->conn;
6591         files_struct *fsp;
6592
6593         req = tevent_req_create(smb1req, &state,
6594                         struct reply_tdis_state);
6595         if (req == NULL) {
6596                 return NULL;
6597         }
6598         state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6599         if (tevent_req_nomem(state->wait_queue, req)) {
6600                 TALLOC_FREE(req);
6601                 return NULL;
6602         }
6603
6604         /*
6605          * Make sure that no new request will be able to use this tcon.
6606          * This ensures that once all outstanding fsp->aio_requests
6607          * on this tcon are done, we are safe to close it.
6608          */
6609         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6610
6611         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6612                 if (fsp->conn != conn) {
6613                         continue;
6614                 }
6615                 /*
6616                  * Flag the file as close in progress.
6617                  * This will prevent any more IO being
6618                  * done on it. Not strictly needed, but
6619                  * doesn't hurt to flag it as closing.
6620                  */
6621                 fsp->fsp_flags.closing = true;
6622
6623                 if (fsp->num_aio_requests > 0) {
6624                         /*
6625                          * Now wait until all aio requests on this fsp are
6626                          * finished.
6627                          *
6628                          * We don't set a callback, as we just want to block the
6629                          * wait queue and the talloc_free() of fsp->aio_request
6630                          * will remove the item from the wait queue.
6631                          */
6632                         subreq = tevent_queue_wait_send(fsp->aio_requests,
6633                                                 conn->sconn->ev_ctx,
6634                                                 state->wait_queue);
6635                         if (tevent_req_nomem(subreq, req)) {
6636                                 TALLOC_FREE(req);
6637                                 return NULL;
6638                         }
6639                 }
6640         }
6641
6642         /*
6643          * Now we add our own waiter to the end of the queue,
6644          * this way we get notified when all pending requests are finished
6645          * and reply to the outstanding SMB1 request.
6646          */
6647         subreq = tevent_queue_wait_send(state,
6648                                 conn->sconn->ev_ctx,
6649                                 state->wait_queue);
6650         if (tevent_req_nomem(subreq, req)) {
6651                 TALLOC_FREE(req);
6652                 return NULL;
6653         }
6654
6655         /*
6656          * We're really going async - move the SMB1 request from
6657          * a talloc stackframe above us to the sconn talloc-context.
6658          * We need this to stick around until the wait_done
6659          * callback is invoked.
6660          */
6661         smb1req = talloc_move(smb1req->sconn, &smb1req);
6662
6663         tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6664
6665         return req;
6666 }
6667
6668 static void reply_tdis_wait_done(struct tevent_req *subreq)
6669 {
6670         struct tevent_req *req = tevent_req_callback_data(
6671                 subreq, struct tevent_req);
6672
6673         tevent_queue_wait_recv(subreq);
6674         TALLOC_FREE(subreq);
6675         tevent_req_done(req);
6676 }
6677
6678 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6679 {
6680         return tevent_req_simple_recv_ntstatus(req);
6681 }
6682
6683 static void reply_tdis_done(struct tevent_req *req)
6684 {
6685         struct smb_request *smb1req = tevent_req_callback_data(
6686                 req, struct smb_request);
6687         NTSTATUS status;
6688         struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6689         bool ok;
6690
6691         /*
6692          * Take the profile charge here. Not strictly
6693          * correct but better than the other SMB1 async
6694          * code that double-charges at the moment.
6695          */
6696         START_PROFILE(SMBtdis);
6697
6698         status = reply_tdis_recv(req);
6699         TALLOC_FREE(req);
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 TALLOC_FREE(smb1req);
6702                 END_PROFILE(SMBtdis);
6703                 exit_server(__location__ ": reply_tdis_recv failed");
6704                 return;
6705         }
6706
6707         /*
6708          * As we've been awoken, we may have changed
6709          * directory in the meantime.
6710          * reply_tdis() has the DO_CHDIR flag set.
6711          */
6712         ok = chdir_current_service(smb1req->conn);
6713         if (!ok) {
6714                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6715                 smb_request_done(smb1req);
6716                 END_PROFILE(SMBtdis);
6717         }
6718
6719         status = smbXsrv_tcon_disconnect(tcon,
6720                                          smb1req->vuid);
6721         if (!NT_STATUS_IS_OK(status)) {
6722                 TALLOC_FREE(smb1req);
6723                 END_PROFILE(SMBtdis);
6724                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6725                 return;
6726         }
6727
6728         /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6729         smb1req->conn = NULL;
6730
6731         TALLOC_FREE(tcon);
6732
6733         reply_outbuf(smb1req, 0, 0);
6734         /*
6735          * The following call is needed to push the
6736          * reply data back out the socket after async
6737          * return. Plus it frees smb1req.
6738          */
6739         smb_request_done(smb1req);
6740         END_PROFILE(SMBtdis);
6741 }
6742
6743 /****************************************************************************
6744  Reply to a echo.
6745  conn POINTER CAN BE NULL HERE !
6746 ****************************************************************************/
6747
6748 void reply_echo(struct smb_request *req)
6749 {
6750         connection_struct *conn = req->conn;
6751         struct smb_perfcount_data local_pcd;
6752         struct smb_perfcount_data *cur_pcd;
6753         int smb_reverb;
6754         int seq_num;
6755
6756         START_PROFILE(SMBecho);
6757
6758         smb_init_perfcount_data(&local_pcd);
6759
6760         if (req->wct < 1) {
6761                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6762                 END_PROFILE(SMBecho);
6763                 return;
6764         }
6765
6766         smb_reverb = SVAL(req->vwv+0, 0);
6767
6768         reply_outbuf(req, 1, req->buflen);
6769
6770         /* copy any incoming data back out */
6771         if (req->buflen > 0) {
6772                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6773         }
6774
6775         if (smb_reverb > 100) {
6776                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6777                 smb_reverb = 100;
6778         }
6779
6780         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6781
6782                 /* this makes sure we catch the request pcd */
6783                 if (seq_num == smb_reverb) {
6784                         cur_pcd = &req->pcd;
6785                 } else {
6786                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6787                         cur_pcd = &local_pcd;
6788                 }
6789
6790                 SSVAL(req->outbuf,smb_vwv0,seq_num);
6791
6792                 show_msg((char *)req->outbuf);
6793                 if (!srv_send_smb(req->xconn,
6794                                 (char *)req->outbuf,
6795                                 true, req->seqnum+1,
6796                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6797                                 cur_pcd))
6798                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
6799         }
6800
6801         DEBUG(3,("echo %d times\n", smb_reverb));
6802
6803         TALLOC_FREE(req->outbuf);
6804
6805         END_PROFILE(SMBecho);
6806         return;
6807 }
6808
6809 /****************************************************************************
6810  Reply to a printopen.
6811 ****************************************************************************/
6812
6813 void reply_printopen(struct smb_request *req)
6814 {
6815         connection_struct *conn = req->conn;
6816         files_struct *fsp;
6817         NTSTATUS status;
6818
6819         START_PROFILE(SMBsplopen);
6820
6821         if (req->wct < 2) {
6822                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6823                 END_PROFILE(SMBsplopen);
6824                 return;
6825         }
6826
6827         if (!CAN_PRINT(conn)) {
6828                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6829                 END_PROFILE(SMBsplopen);
6830                 return;
6831         }
6832
6833         status = file_new(req, conn, &fsp);
6834         if(!NT_STATUS_IS_OK(status)) {
6835                 reply_nterror(req, status);
6836                 END_PROFILE(SMBsplopen);
6837                 return;
6838         }
6839
6840         /* Open for exclusive use, write only. */
6841         status = print_spool_open(fsp, NULL, req->vuid);
6842
6843         if (!NT_STATUS_IS_OK(status)) {
6844                 file_free(req, fsp);
6845                 reply_nterror(req, status);
6846                 END_PROFILE(SMBsplopen);
6847                 return;
6848         }
6849
6850         reply_outbuf(req, 1, 0);
6851         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6852
6853         DEBUG(3,("openprint fd=%d %s\n",
6854                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6855
6856         END_PROFILE(SMBsplopen);
6857         return;
6858 }
6859
6860 /****************************************************************************
6861  Reply to a printclose.
6862 ****************************************************************************/
6863
6864 void reply_printclose(struct smb_request *req)
6865 {
6866         connection_struct *conn = req->conn;
6867         files_struct *fsp;
6868         NTSTATUS status;
6869
6870         START_PROFILE(SMBsplclose);
6871
6872         if (req->wct < 1) {
6873                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6874                 END_PROFILE(SMBsplclose);
6875                 return;
6876         }
6877
6878         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6879
6880         if (!check_fsp(conn, req, fsp)) {
6881                 END_PROFILE(SMBsplclose);
6882                 return;
6883         }
6884
6885         if (!CAN_PRINT(conn)) {
6886                 reply_force_doserror(req, ERRSRV, ERRerror);
6887                 END_PROFILE(SMBsplclose);
6888                 return;
6889         }
6890
6891         DEBUG(3,("printclose fd=%d %s\n",
6892                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6893
6894         status = close_file(req, fsp, NORMAL_CLOSE);
6895
6896         if(!NT_STATUS_IS_OK(status)) {
6897                 reply_nterror(req, status);
6898                 END_PROFILE(SMBsplclose);
6899                 return;
6900         }
6901
6902         reply_outbuf(req, 0, 0);
6903
6904         END_PROFILE(SMBsplclose);
6905         return;
6906 }
6907
6908 /****************************************************************************
6909  Reply to a printqueue.
6910 ****************************************************************************/
6911
6912 void reply_printqueue(struct smb_request *req)
6913 {
6914         const struct loadparm_substitution *lp_sub =
6915                 loadparm_s3_global_substitution();
6916         connection_struct *conn = req->conn;
6917         int max_count;
6918         int start_index;
6919
6920         START_PROFILE(SMBsplretq);
6921
6922         if (req->wct < 2) {
6923                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6924                 END_PROFILE(SMBsplretq);
6925                 return;
6926         }
6927
6928         max_count = SVAL(req->vwv+0, 0);
6929         start_index = SVAL(req->vwv+1, 0);
6930
6931         /* we used to allow the client to get the cnum wrong, but that
6932            is really quite gross and only worked when there was only
6933            one printer - I think we should now only accept it if they
6934            get it right (tridge) */
6935         if (!CAN_PRINT(conn)) {
6936                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6937                 END_PROFILE(SMBsplretq);
6938                 return;
6939         }
6940
6941         reply_outbuf(req, 2, 3);
6942         SSVAL(req->outbuf,smb_vwv0,0);
6943         SSVAL(req->outbuf,smb_vwv1,0);
6944         SCVAL(smb_buf(req->outbuf),0,1);
6945         SSVAL(smb_buf(req->outbuf),1,0);
6946
6947         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6948                  start_index, max_count));
6949
6950         {
6951                 TALLOC_CTX *mem_ctx = talloc_tos();
6952                 NTSTATUS status;
6953                 WERROR werr;
6954                 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6955                 struct rpc_pipe_client *cli = NULL;
6956                 struct dcerpc_binding_handle *b = NULL;
6957                 struct policy_handle handle;
6958                 struct spoolss_DevmodeContainer devmode_ctr;
6959                 union spoolss_JobInfo *info;
6960                 uint32_t count;
6961                 uint32_t num_to_get;
6962                 uint32_t first;
6963                 uint32_t i;
6964
6965                 ZERO_STRUCT(handle);
6966
6967                 status = rpc_pipe_open_interface(mem_ctx,
6968                                                  &ndr_table_spoolss,
6969                                                  conn->session_info,
6970                                                  conn->sconn->remote_address,
6971                                                  conn->sconn->local_address,
6972                                                  conn->sconn->msg_ctx,
6973                                                  &cli);
6974                 if (!NT_STATUS_IS_OK(status)) {
6975                         DEBUG(0, ("reply_printqueue: "
6976                                   "could not connect to spoolss: %s\n",
6977                                   nt_errstr(status)));
6978                         reply_nterror(req, status);
6979                         goto out;
6980                 }
6981                 b = cli->binding_handle;
6982
6983                 ZERO_STRUCT(devmode_ctr);
6984
6985                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6986                                                 sharename,
6987                                                 NULL, devmode_ctr,
6988                                                 SEC_FLAG_MAXIMUM_ALLOWED,
6989                                                 &handle,
6990                                                 &werr);
6991                 if (!NT_STATUS_IS_OK(status)) {
6992                         reply_nterror(req, status);
6993                         goto out;
6994                 }
6995                 if (!W_ERROR_IS_OK(werr)) {
6996                         reply_nterror(req, werror_to_ntstatus(werr));
6997                         goto out;
6998                 }
6999
7000                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
7001                                                &handle,
7002                                                0, /* firstjob */
7003                                                0xff, /* numjobs */
7004                                                2, /* level */
7005                                                0, /* offered */
7006                                                &count,
7007                                                &info);
7008                 if (!W_ERROR_IS_OK(werr)) {
7009                         reply_nterror(req, werror_to_ntstatus(werr));
7010                         goto out;
7011                 }
7012
7013                 if (max_count > 0) {
7014                         first = start_index;
7015                 } else {
7016                         first = start_index + max_count + 1;
7017                 }
7018
7019                 if (first >= count) {
7020                         num_to_get = first;
7021                 } else {
7022                         num_to_get = first + MIN(ABS(max_count), count - first);
7023                 }
7024
7025                 for (i = first; i < num_to_get; i++) {
7026                         char blob[28];
7027                         char *p = blob;
7028                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
7029                         int qstatus;
7030                         size_t len = 0;
7031                         uint16_t qrapjobid = pjobid_to_rap(sharename,
7032                                                         info[i].info2.job_id);
7033
7034                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
7035                                 qstatus = 2;
7036                         } else {
7037                                 qstatus = 3;
7038                         }
7039
7040                         srv_put_dos_date2(p, 0, qtime);
7041                         SCVAL(p, 4, qstatus);
7042                         SSVAL(p, 5, qrapjobid);
7043                         SIVAL(p, 7, info[i].info2.size);
7044                         SCVAL(p, 11, 0);
7045                         status = srvstr_push(blob, req->flags2, p+12,
7046                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
7047                         if (!NT_STATUS_IS_OK(status)) {
7048                                 reply_nterror(req, status);
7049                                 goto out;
7050                         }
7051                         if (message_push_blob(
7052                                     &req->outbuf,
7053                                     data_blob_const(
7054                                             blob, sizeof(blob))) == -1) {
7055                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7056                                 goto out;
7057                         }
7058                 }
7059
7060                 if (count > 0) {
7061                         SSVAL(req->outbuf,smb_vwv0,count);
7062                         SSVAL(req->outbuf,smb_vwv1,
7063                               (max_count>0?first+count:first-1));
7064                         SCVAL(smb_buf(req->outbuf),0,1);
7065                         SSVAL(smb_buf(req->outbuf),1,28*count);
7066                 }
7067
7068
7069                 DEBUG(3, ("%u entries returned in queue\n",
7070                           (unsigned)count));
7071
7072 out:
7073                 if (b && is_valid_policy_hnd(&handle)) {
7074                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7075                 }
7076
7077         }
7078
7079         END_PROFILE(SMBsplretq);
7080         return;
7081 }
7082
7083 /****************************************************************************
7084  Reply to a printwrite.
7085 ****************************************************************************/
7086
7087 void reply_printwrite(struct smb_request *req)
7088 {
7089         connection_struct *conn = req->conn;
7090         int numtowrite;
7091         const char *data;
7092         files_struct *fsp;
7093
7094         START_PROFILE(SMBsplwr);
7095
7096         if (req->wct < 1) {
7097                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7098                 END_PROFILE(SMBsplwr);
7099                 return;
7100         }
7101
7102         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7103
7104         if (!check_fsp(conn, req, fsp)) {
7105                 END_PROFILE(SMBsplwr);
7106                 return;
7107         }
7108
7109         if (!fsp->print_file) {
7110                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7111                 END_PROFILE(SMBsplwr);
7112                 return;
7113         }
7114
7115         if (!CHECK_WRITE(fsp)) {
7116                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7117                 END_PROFILE(SMBsplwr);
7118                 return;
7119         }
7120
7121         numtowrite = SVAL(req->buf, 1);
7122
7123         /*
7124          * This already protects us against CVE-2017-12163.
7125          */
7126         if (req->buflen < numtowrite + 3) {
7127                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7128                 END_PROFILE(SMBsplwr);
7129                 return;
7130         }
7131
7132         data = (const char *)req->buf + 3;
7133
7134         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7135                 reply_nterror(req, map_nt_error_from_unix(errno));
7136                 END_PROFILE(SMBsplwr);
7137                 return;
7138         }
7139
7140         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7141
7142         END_PROFILE(SMBsplwr);
7143         return;
7144 }
7145
7146 /****************************************************************************
7147  Reply to a mkdir.
7148 ****************************************************************************/
7149
7150 void reply_mkdir(struct smb_request *req)
7151 {
7152         connection_struct *conn = req->conn;
7153         struct smb_filename *smb_dname = NULL;
7154         char *directory = NULL;
7155         NTSTATUS status;
7156         uint32_t ucf_flags;
7157         TALLOC_CTX *ctx = talloc_tos();
7158
7159         START_PROFILE(SMBmkdir);
7160
7161         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7162                             STR_TERMINATE, &status);
7163         if (!NT_STATUS_IS_OK(status)) {
7164                 reply_nterror(req, status);
7165                 goto out;
7166         }
7167
7168         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7169         status = filename_convert(ctx, conn,
7170                                  directory,
7171                                  ucf_flags,
7172                                  0,
7173                                  NULL,
7174                                  &smb_dname);
7175         if (!NT_STATUS_IS_OK(status)) {
7176                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7177                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7178                                         ERRSRV, ERRbadpath);
7179                         goto out;
7180                 }
7181                 reply_nterror(req, status);
7182                 goto out;
7183         }
7184
7185         status = create_directory(conn, req, smb_dname);
7186
7187         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7188
7189         if (!NT_STATUS_IS_OK(status)) {
7190
7191                 if (!use_nt_status()
7192                     && NT_STATUS_EQUAL(status,
7193                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
7194                         /*
7195                          * Yes, in the DOS error code case we get a
7196                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7197                          * samba4 torture test.
7198                          */
7199                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7200                 }
7201
7202                 reply_nterror(req, status);
7203                 goto out;
7204         }
7205
7206         reply_outbuf(req, 0, 0);
7207
7208         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7209  out:
7210         TALLOC_FREE(smb_dname);
7211         END_PROFILE(SMBmkdir);
7212         return;
7213 }
7214
7215 /****************************************************************************
7216  Reply to a rmdir.
7217 ****************************************************************************/
7218
7219 void reply_rmdir(struct smb_request *req)
7220 {
7221         connection_struct *conn = req->conn;
7222         struct smb_filename *smb_dname = NULL;
7223         char *directory = NULL;
7224         NTSTATUS status;
7225         TALLOC_CTX *ctx = talloc_tos();
7226         files_struct *fsp = NULL;
7227         int info = 0;
7228         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7229
7230         START_PROFILE(SMBrmdir);
7231
7232         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7233                             STR_TERMINATE, &status);
7234         if (!NT_STATUS_IS_OK(status)) {
7235                 reply_nterror(req, status);
7236                 goto out;
7237         }
7238
7239         status = filename_convert(ctx, conn,
7240                                  directory,
7241                                  ucf_flags,
7242                                  0,
7243                                  NULL,
7244                                  &smb_dname);
7245         if (!NT_STATUS_IS_OK(status)) {
7246                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7247                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7248                                         ERRSRV, ERRbadpath);
7249                         goto out;
7250                 }
7251                 reply_nterror(req, status);
7252                 goto out;
7253         }
7254
7255         if (is_ntfs_stream_smb_fname(smb_dname)) {
7256                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7257                 goto out;
7258         }
7259
7260         status = SMB_VFS_CREATE_FILE(
7261                 conn,                                   /* conn */
7262                 req,                                    /* req */
7263                 &conn->cwd_fsp,                         /* dirfsp */
7264                 smb_dname,                              /* fname */
7265                 DELETE_ACCESS,                          /* access_mask */
7266                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7267                         FILE_SHARE_DELETE),
7268                 FILE_OPEN,                              /* create_disposition*/
7269                 FILE_DIRECTORY_FILE,                    /* create_options */
7270                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
7271                 0,                                      /* oplock_request */
7272                 NULL,                                   /* lease */
7273                 0,                                      /* allocation_size */
7274                 0,                                      /* private_flags */
7275                 NULL,                                   /* sd */
7276                 NULL,                                   /* ea_list */
7277                 &fsp,                                   /* result */
7278                 &info,                                  /* pinfo */
7279                 NULL, NULL);                            /* create context */
7280
7281         if (!NT_STATUS_IS_OK(status)) {
7282                 if (open_was_deferred(req->xconn, req->mid)) {
7283                         /* We have re-scheduled this call. */
7284                         goto out;
7285                 }
7286                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7287                         bool ok = defer_smb1_sharing_violation(req);
7288                         if (ok) {
7289                                 goto out;
7290                         }
7291                 }
7292                 reply_nterror(req, status);
7293                 goto out;
7294         }
7295
7296         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7297         if (!NT_STATUS_IS_OK(status)) {
7298                 close_file(req, fsp, ERROR_CLOSE);
7299                 reply_nterror(req, status);
7300                 goto out;
7301         }
7302
7303         if (!set_delete_on_close(fsp, true,
7304                         conn->session_info->security_token,
7305                         conn->session_info->unix_token)) {
7306                 close_file(req, fsp, ERROR_CLOSE);
7307                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7308                 goto out;
7309         }
7310
7311         status = close_file(req, fsp, NORMAL_CLOSE);
7312         if (!NT_STATUS_IS_OK(status)) {
7313                 reply_nterror(req, status);
7314         } else {
7315                 reply_outbuf(req, 0, 0);
7316         }
7317
7318         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7319  out:
7320         TALLOC_FREE(smb_dname);
7321         END_PROFILE(SMBrmdir);
7322         return;
7323 }
7324
7325 /*******************************************************************
7326  Resolve wildcards in a filename rename.
7327 ********************************************************************/
7328
7329 static bool resolve_wildcards(TALLOC_CTX *ctx,
7330                                 const char *name1,
7331                                 const char *name2,
7332                                 char **pp_newname)
7333 {
7334         char *name2_copy = NULL;
7335         char *root1 = NULL;
7336         char *root2 = NULL;
7337         char *ext1 = NULL;
7338         char *ext2 = NULL;
7339         char *p,*p2, *pname1, *pname2;
7340
7341         name2_copy = talloc_strdup(ctx, name2);
7342         if (!name2_copy) {
7343                 return False;
7344         }
7345
7346         pname1 = strrchr_m(name1,'/');
7347         pname2 = strrchr_m(name2_copy,'/');
7348
7349         if (!pname1 || !pname2) {
7350                 return False;
7351         }
7352
7353         /* Truncate the copy of name2 at the last '/' */
7354         *pname2 = '\0';
7355
7356         /* Now go past the '/' */
7357         pname1++;
7358         pname2++;
7359
7360         root1 = talloc_strdup(ctx, pname1);
7361         root2 = talloc_strdup(ctx, pname2);
7362
7363         if (!root1 || !root2) {
7364                 return False;
7365         }
7366
7367         p = strrchr_m(root1,'.');
7368         if (p) {
7369                 *p = 0;
7370                 ext1 = talloc_strdup(ctx, p+1);
7371         } else {
7372                 ext1 = talloc_strdup(ctx, "");
7373         }
7374         p = strrchr_m(root2,'.');
7375         if (p) {
7376                 *p = 0;
7377                 ext2 = talloc_strdup(ctx, p+1);
7378         } else {
7379                 ext2 = talloc_strdup(ctx, "");
7380         }
7381
7382         if (!ext1 || !ext2) {
7383                 return False;
7384         }
7385
7386         p = root1;
7387         p2 = root2;
7388         while (*p2) {
7389                 if (*p2 == '?') {
7390                         /* Hmmm. Should this be mb-aware ? */
7391                         *p2 = *p;
7392                         p2++;
7393                 } else if (*p2 == '*') {
7394                         *p2 = '\0';
7395                         root2 = talloc_asprintf(ctx, "%s%s",
7396                                                 root2,
7397                                                 p);
7398                         if (!root2) {
7399                                 return False;
7400                         }
7401                         break;
7402                 } else {
7403                         p2++;
7404                 }
7405                 if (*p) {
7406                         p++;
7407                 }
7408         }
7409
7410         p = ext1;
7411         p2 = ext2;
7412         while (*p2) {
7413                 if (*p2 == '?') {
7414                         /* Hmmm. Should this be mb-aware ? */
7415                         *p2 = *p;
7416                         p2++;
7417                 } else if (*p2 == '*') {
7418                         *p2 = '\0';
7419                         ext2 = talloc_asprintf(ctx, "%s%s",
7420                                                 ext2,
7421                                                 p);
7422                         if (!ext2) {
7423                                 return False;
7424                         }
7425                         break;
7426                 } else {
7427                         p2++;
7428                 }
7429                 if (*p) {
7430                         p++;
7431                 }
7432         }
7433
7434         if (*ext2) {
7435                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7436                                 name2_copy,
7437                                 root2,
7438                                 ext2);
7439         } else {
7440                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7441                                 name2_copy,
7442                                 root2);
7443         }
7444
7445         if (!*pp_newname) {
7446                 return False;
7447         }
7448
7449         return True;
7450 }
7451
7452 /****************************************************************************
7453  Ensure open files have their names updated. Updated to notify other smbd's
7454  asynchronously.
7455 ****************************************************************************/
7456
7457 static void rename_open_files(connection_struct *conn,
7458                               struct share_mode_lock *lck,
7459                               struct file_id id,
7460                               uint32_t orig_name_hash,
7461                               const struct smb_filename *smb_fname_dst)
7462 {
7463         files_struct *fsp;
7464         bool did_rename = False;
7465         NTSTATUS status;
7466         uint32_t new_name_hash = 0;
7467
7468         for(fsp = file_find_di_first(conn->sconn, id); fsp;
7469             fsp = file_find_di_next(fsp)) {
7470                 struct file_id_buf idbuf;
7471                 /* fsp_name is a relative path under the fsp. To change this for other
7472                    sharepaths we need to manipulate relative paths. */
7473                 /* TODO - create the absolute path and manipulate the newname
7474                    relative to the sharepath. */
7475                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7476                         continue;
7477                 }
7478                 if (fsp->name_hash != orig_name_hash) {
7479                         continue;
7480                 }
7481                 DBG_DEBUG("renaming file %s "
7482                           "(file_id %s) from %s -> %s\n",
7483                           fsp_fnum_dbg(fsp),
7484                           file_id_str_buf(fsp->file_id, &idbuf),
7485                           fsp_str_dbg(fsp),
7486                           smb_fname_str_dbg(smb_fname_dst));
7487
7488                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7489                 if (NT_STATUS_IS_OK(status)) {
7490                         did_rename = True;
7491                         new_name_hash = fsp->name_hash;
7492                 }
7493         }
7494
7495         if (!did_rename) {
7496                 struct file_id_buf idbuf;
7497                 DBG_DEBUG("no open files on file_id %s "
7498                           "for %s\n",
7499                           file_id_str_buf(id, &idbuf),
7500                           smb_fname_str_dbg(smb_fname_dst));
7501         }
7502
7503         /* Send messages to all smbd's (not ourself) that the name has changed. */
7504         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7505                               orig_name_hash, new_name_hash,
7506                               smb_fname_dst);
7507
7508 }
7509
7510 /****************************************************************************
7511  We need to check if the source path is a parent directory of the destination
7512  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7513  refuse the rename with a sharing violation. Under UNIX the above call can
7514  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7515  probably need to check that the client is a Windows one before disallowing
7516  this as a UNIX client (one with UNIX extensions) can know the source is a
7517  symlink and make this decision intelligently. Found by an excellent bug
7518  report from <AndyLiebman@aol.com>.
7519 ****************************************************************************/
7520
7521 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7522                                      const struct smb_filename *smb_fname_dst)
7523 {
7524         const char *psrc = smb_fname_src->base_name;
7525         const char *pdst = smb_fname_dst->base_name;
7526         size_t slen;
7527
7528         if (psrc[0] == '.' && psrc[1] == '/') {
7529                 psrc += 2;
7530         }
7531         if (pdst[0] == '.' && pdst[1] == '/') {
7532                 pdst += 2;
7533         }
7534         if ((slen = strlen(psrc)) > strlen(pdst)) {
7535                 return False;
7536         }
7537         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7538 }
7539
7540 /*
7541  * Do the notify calls from a rename
7542  */
7543
7544 static void notify_rename(connection_struct *conn, bool is_dir,
7545                           const struct smb_filename *smb_fname_src,
7546                           const struct smb_filename *smb_fname_dst)
7547 {
7548         char *parent_dir_src = NULL;
7549         char *parent_dir_dst = NULL;
7550         uint32_t mask;
7551
7552         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7553                 : FILE_NOTIFY_CHANGE_FILE_NAME;
7554
7555         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7556                             &parent_dir_src, NULL) ||
7557             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7558                             &parent_dir_dst, NULL)) {
7559                 goto out;
7560         }
7561
7562         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7563                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7564                              smb_fname_src->base_name);
7565                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7566                              smb_fname_dst->base_name);
7567         }
7568         else {
7569                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7570                              smb_fname_src->base_name);
7571                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7572                              smb_fname_dst->base_name);
7573         }
7574
7575         /* this is a strange one. w2k3 gives an additional event for
7576            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7577            files, but not directories */
7578         if (!is_dir) {
7579                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7580                              FILE_NOTIFY_CHANGE_ATTRIBUTES
7581                              |FILE_NOTIFY_CHANGE_CREATION,
7582                              smb_fname_dst->base_name);
7583         }
7584  out:
7585         TALLOC_FREE(parent_dir_src);
7586         TALLOC_FREE(parent_dir_dst);
7587 }
7588
7589 /****************************************************************************
7590  Returns an error if the parent directory for a filename is open in an
7591  incompatible way.
7592 ****************************************************************************/
7593
7594 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7595                                         const struct smb_filename *smb_fname_dst_in)
7596 {
7597         struct smb_filename *smb_fname_parent = NULL;
7598         struct file_id id;
7599         files_struct *fsp = NULL;
7600         int ret;
7601         bool ok;
7602
7603         ok = parent_smb_fname(talloc_tos(),
7604                               smb_fname_dst_in,
7605                               &smb_fname_parent,
7606                               NULL);
7607         if (!ok) {
7608                 return NT_STATUS_NO_MEMORY;
7609         }
7610
7611         ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7612         if (ret == -1) {
7613                 return map_nt_error_from_unix(errno);
7614         }
7615
7616         /*
7617          * We're only checking on this smbd here, mostly good
7618          * enough.. and will pass tests.
7619          */
7620
7621         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7622         for (fsp = file_find_di_first(conn->sconn, id); fsp;
7623                         fsp = file_find_di_next(fsp)) {
7624                 if (fsp->access_mask & DELETE_ACCESS) {
7625                         return NT_STATUS_SHARING_VIOLATION;
7626                 }
7627         }
7628         return NT_STATUS_OK;
7629 }
7630
7631 /****************************************************************************
7632  Rename an open file - given an fsp.
7633 ****************************************************************************/
7634
7635 NTSTATUS rename_internals_fsp(connection_struct *conn,
7636                         files_struct *fsp,
7637                         const struct smb_filename *smb_fname_dst_in,
7638                         const char *dst_original_lcomp,
7639                         uint32_t attrs,
7640                         bool replace_if_exists)
7641 {
7642         TALLOC_CTX *ctx = talloc_tos();
7643         struct smb_filename *smb_fname_dst = NULL;
7644         NTSTATUS status = NT_STATUS_OK;
7645         struct share_mode_lock *lck = NULL;
7646         uint32_t access_mask = SEC_DIR_ADD_FILE;
7647         bool dst_exists, old_is_stream, new_is_stream;
7648         int ret;
7649
7650         status = check_name(conn, smb_fname_dst_in);
7651         if (!NT_STATUS_IS_OK(status)) {
7652                 return status;
7653         }
7654
7655         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7656         if (!NT_STATUS_IS_OK(status)) {
7657                 return status;
7658         }
7659
7660         if (file_has_open_streams(fsp)) {
7661                 return NT_STATUS_ACCESS_DENIED;
7662         }
7663
7664         /* Make a copy of the dst smb_fname structs */
7665
7666         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7667         if (smb_fname_dst == NULL) {
7668                 status = NT_STATUS_NO_MEMORY;
7669                 goto out;
7670         }
7671
7672         /*
7673          * Check for special case with case preserving and not
7674          * case sensitive. If the new last component differs from the original
7675          * last component only by case, then we should allow
7676          * the rename (user is trying to change the case of the
7677          * filename).
7678          */
7679         if (!conn->case_sensitive && conn->case_preserve &&
7680             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7681             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7682                 char *fname_dst_parent = NULL;
7683                 const char *fname_dst_lcomp = NULL;
7684                 char *orig_lcomp_path = NULL;
7685                 char *orig_lcomp_stream = NULL;
7686                 bool ok = true;
7687
7688                 /*
7689                  * Split off the last component of the processed
7690                  * destination name. We will compare this to
7691                  * the split components of dst_original_lcomp.
7692                  */
7693                 if (!parent_dirname(ctx,
7694                                 smb_fname_dst->base_name,
7695                                 &fname_dst_parent,
7696                                 &fname_dst_lcomp)) {
7697                         status = NT_STATUS_NO_MEMORY;
7698                         goto out;
7699                 }
7700
7701                 /*
7702                  * The dst_original_lcomp component contains
7703                  * the last_component of the path + stream
7704                  * name (if a stream exists).
7705                  *
7706                  * Split off the stream name so we
7707                  * can check them separately.
7708                  */
7709
7710                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7711                         /* POSIX - no stream component. */
7712                         orig_lcomp_path = talloc_strdup(ctx,
7713                                                 dst_original_lcomp);
7714                         if (orig_lcomp_path == NULL) {
7715                                 ok = false;
7716                         }
7717                 } else {
7718                         ok = split_stream_filename(ctx,
7719                                         dst_original_lcomp,
7720                                         &orig_lcomp_path,
7721                                         &orig_lcomp_stream);
7722                 }
7723
7724                 if (!ok) {
7725                         TALLOC_FREE(fname_dst_parent);
7726                         status = NT_STATUS_NO_MEMORY;
7727                         goto out;
7728                 }
7729
7730                 /* If the base names only differ by case, use original. */
7731                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7732                         char *tmp;
7733                         /*
7734                          * Replace the modified last component with the
7735                          * original.
7736                          */
7737                         if (!ISDOT(fname_dst_parent)) {
7738                                 tmp = talloc_asprintf(smb_fname_dst,
7739                                         "%s/%s",
7740                                         fname_dst_parent,
7741                                         orig_lcomp_path);
7742                         } else {
7743                                 tmp = talloc_strdup(smb_fname_dst,
7744                                         orig_lcomp_path);
7745                         }
7746                         if (tmp == NULL) {
7747                                 status = NT_STATUS_NO_MEMORY;
7748                                 TALLOC_FREE(fname_dst_parent);
7749                                 TALLOC_FREE(orig_lcomp_path);
7750                                 TALLOC_FREE(orig_lcomp_stream);
7751                                 goto out;
7752                         }
7753                         TALLOC_FREE(smb_fname_dst->base_name);
7754                         smb_fname_dst->base_name = tmp;
7755                 }
7756
7757                 /* If the stream_names only differ by case, use original. */
7758                 if(!strcsequal(smb_fname_dst->stream_name,
7759                                orig_lcomp_stream)) {
7760                         /* Use the original stream. */
7761                         char *tmp = talloc_strdup(smb_fname_dst,
7762                                             orig_lcomp_stream);
7763                         if (tmp == NULL) {
7764                                 status = NT_STATUS_NO_MEMORY;
7765                                 TALLOC_FREE(fname_dst_parent);
7766                                 TALLOC_FREE(orig_lcomp_path);
7767                                 TALLOC_FREE(orig_lcomp_stream);
7768                                 goto out;
7769                         }
7770                         TALLOC_FREE(smb_fname_dst->stream_name);
7771                         smb_fname_dst->stream_name = tmp;
7772                 }
7773                 TALLOC_FREE(fname_dst_parent);
7774                 TALLOC_FREE(orig_lcomp_path);
7775                 TALLOC_FREE(orig_lcomp_stream);
7776         }
7777
7778         /*
7779          * If the src and dest names are identical - including case,
7780          * don't do the rename, just return success.
7781          */
7782
7783         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7784             strcsequal(fsp->fsp_name->stream_name,
7785                        smb_fname_dst->stream_name)) {
7786                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7787                           "- returning success\n",
7788                           smb_fname_str_dbg(smb_fname_dst)));
7789                 status = NT_STATUS_OK;
7790                 goto out;
7791         }
7792
7793         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7794         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7795
7796         /* Return the correct error code if both names aren't streams. */
7797         if (!old_is_stream && new_is_stream) {
7798                 status = NT_STATUS_OBJECT_NAME_INVALID;
7799                 goto out;
7800         }
7801
7802         if (old_is_stream && !new_is_stream) {
7803                 status = NT_STATUS_INVALID_PARAMETER;
7804                 goto out;
7805         }
7806
7807         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7808
7809         if(!replace_if_exists && dst_exists) {
7810                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7811                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7812                           smb_fname_str_dbg(smb_fname_dst)));
7813                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7814                 goto out;
7815         }
7816
7817         if (dst_exists) {
7818                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7819                     &smb_fname_dst->st);
7820                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7821                                                            fileid);
7822                 /* The file can be open when renaming a stream */
7823                 if (dst_fsp && !new_is_stream) {
7824                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7825                         status = NT_STATUS_ACCESS_DENIED;
7826                         goto out;
7827                 }
7828         }
7829
7830         /* Ensure we have a valid stat struct for the source. */
7831         status = vfs_stat_fsp(fsp);
7832         if (!NT_STATUS_IS_OK(status)) {
7833                 goto out;
7834         }
7835
7836         status = can_rename(conn, fsp, attrs);
7837
7838         if (!NT_STATUS_IS_OK(status)) {
7839                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7840                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7841                           smb_fname_str_dbg(smb_fname_dst)));
7842                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7843                         status = NT_STATUS_ACCESS_DENIED;
7844                 goto out;
7845         }
7846
7847         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7848                 status = NT_STATUS_ACCESS_DENIED;
7849                 goto out;
7850         }
7851
7852         /* Do we have rights to move into the destination ? */
7853         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7854                 /* We're moving a directory. */
7855                 access_mask = SEC_DIR_ADD_SUBDIR;
7856         }
7857         status = check_parent_access(conn,
7858                                 conn->cwd_fsp,
7859                                 smb_fname_dst,
7860                                 access_mask);
7861         if (!NT_STATUS_IS_OK(status)) {
7862                 DBG_INFO("check_parent_access on "
7863                         "dst %s returned %s\n",
7864                         smb_fname_str_dbg(smb_fname_dst),
7865                         nt_errstr(status));
7866                 goto out;
7867         }
7868
7869         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7870
7871         /*
7872          * We have the file open ourselves, so not being able to get the
7873          * corresponding share mode lock is a fatal error.
7874          */
7875
7876         SMB_ASSERT(lck != NULL);
7877
7878         ret = SMB_VFS_RENAMEAT(conn,
7879                         conn->cwd_fsp,
7880                         fsp->fsp_name,
7881                         conn->cwd_fsp,
7882                         smb_fname_dst);
7883         if (ret == 0) {
7884                 uint32_t create_options = fsp->fh->private_options;
7885
7886                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7887                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7888                           smb_fname_str_dbg(smb_fname_dst)));
7889
7890                 if (!fsp->fsp_flags.is_directory &&
7891                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7892                     (lp_map_archive(SNUM(conn)) ||
7893                     lp_store_dos_attributes(SNUM(conn)))) {
7894                         /* We must set the archive bit on the newly
7895                            renamed file. */
7896                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7897                                 uint32_t old_dosmode = dos_mode(conn,
7898                                                         smb_fname_dst);
7899                                 file_set_dosmode(conn,
7900                                         smb_fname_dst,
7901                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7902                                         NULL,
7903                                         true);
7904                         }
7905                 }
7906
7907                 notify_rename(conn,
7908                               fsp->fsp_flags.is_directory,
7909                               fsp->fsp_name,
7910                               smb_fname_dst);
7911
7912                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7913                                   smb_fname_dst);
7914
7915                 /*
7916                  * A rename acts as a new file create w.r.t. allowing an initial delete
7917                  * on close, probably because in Windows there is a new handle to the
7918                  * new file. If initial delete on close was requested but not
7919                  * originally set, we need to set it here. This is probably not 100% correct,
7920                  * but will work for the CIFSFS client which in non-posix mode
7921                  * depends on these semantics. JRA.
7922                  */
7923
7924                 if (create_options & FILE_DELETE_ON_CLOSE) {
7925                         status = can_set_delete_on_close(fsp, 0);
7926
7927                         if (NT_STATUS_IS_OK(status)) {
7928                                 /* Note that here we set the *initial* delete on close flag,
7929                                  * not the regular one. The magic gets handled in close. */
7930                                 fsp->fsp_flags.initial_delete_on_close = true;
7931                         }
7932                 }
7933                 TALLOC_FREE(lck);
7934                 status = NT_STATUS_OK;
7935                 goto out;
7936         }
7937
7938         TALLOC_FREE(lck);
7939
7940         if (errno == ENOTDIR || errno == EISDIR) {
7941                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7942         } else {
7943                 status = map_nt_error_from_unix(errno);
7944         }
7945
7946         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7947                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7948                   smb_fname_str_dbg(smb_fname_dst)));
7949
7950  out:
7951         TALLOC_FREE(smb_fname_dst);
7952
7953         return status;
7954 }
7955
7956 /****************************************************************************
7957  The guts of the rename command, split out so it may be called by the NT SMB
7958  code.
7959 ****************************************************************************/
7960
7961 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7962                         connection_struct *conn,
7963                         struct smb_request *req,
7964                         struct smb_filename *smb_fname_src,
7965                         struct smb_filename *smb_fname_dst,
7966                         const char *dst_original_lcomp,
7967                         uint32_t attrs,
7968                         bool replace_if_exists,
7969                         bool src_has_wild,
7970                         bool dest_has_wild,
7971                         uint32_t access_mask)
7972 {
7973         char *fname_src_dir = NULL;
7974         struct smb_filename *smb_fname_src_dir = NULL;
7975         char *fname_src_mask = NULL;
7976         int count=0;
7977         NTSTATUS status = NT_STATUS_OK;
7978         struct smb_Dir *dir_hnd = NULL;
7979         const char *dname = NULL;
7980         char *talloced = NULL;
7981         long offset = 0;
7982         int create_options = 0;
7983         bool posix_pathnames = (req != NULL && req->posix_pathnames);
7984         struct smb2_create_blobs *posx = NULL;
7985         int rc;
7986
7987         /*
7988          * Split the old name into directory and last component
7989          * strings. Note that unix_convert may have stripped off a
7990          * leading ./ from both name and newname if the rename is
7991          * at the root of the share. We need to make sure either both
7992          * name and newname contain a / character or neither of them do
7993          * as this is checked in resolve_wildcards().
7994          */
7995
7996         /* Split up the directory from the filename/mask. */
7997         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7998                                       &fname_src_dir, &fname_src_mask);
7999         if (!NT_STATUS_IS_OK(status)) {
8000                 status = NT_STATUS_NO_MEMORY;
8001                 goto out;
8002         }
8003
8004         /*
8005          * We should only check the mangled cache
8006          * here if unix_convert failed. This means
8007          * that the path in 'mask' doesn't exist
8008          * on the file system and so we need to look
8009          * for a possible mangle. This patch from
8010          * Tine Smukavec <valentin.smukavec@hermes.si>.
8011          */
8012
8013         if (!VALID_STAT(smb_fname_src->st) &&
8014             mangle_is_mangled(fname_src_mask, conn->params)) {
8015                 char *new_mask = NULL;
8016                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
8017                                             conn->params);
8018                 if (new_mask) {
8019                         TALLOC_FREE(fname_src_mask);
8020                         fname_src_mask = new_mask;
8021                 }
8022         }
8023
8024         if (posix_pathnames) {
8025                 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8026                 if (!NT_STATUS_IS_OK(status)) {
8027                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8028                                     nt_errstr(status));
8029                         goto out;
8030                 }
8031         }
8032
8033         if (!src_has_wild) {
8034                 files_struct *fsp;
8035
8036                 /*
8037                  * Only one file needs to be renamed. Append the mask back
8038                  * onto the directory.
8039                  */
8040                 TALLOC_FREE(smb_fname_src->base_name);
8041                 if (ISDOT(fname_src_dir)) {
8042                         /* Ensure we use canonical names on open. */
8043                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8044                                                         "%s",
8045                                                         fname_src_mask);
8046                 } else {
8047                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8048                                                         "%s/%s",
8049                                                         fname_src_dir,
8050                                                         fname_src_mask);
8051                 }
8052                 if (!smb_fname_src->base_name) {
8053                         status = NT_STATUS_NO_MEMORY;
8054                         goto out;
8055                 }
8056
8057                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8058                           "case_preserve = %d, short case preserve = %d, "
8059                           "directory = %s, newname = %s, "
8060                           "last_component_dest = %s\n",
8061                           conn->case_sensitive, conn->case_preserve,
8062                           conn->short_case_preserve,
8063                           smb_fname_str_dbg(smb_fname_src),
8064                           smb_fname_str_dbg(smb_fname_dst),
8065                           dst_original_lcomp));
8066
8067                 /* The dest name still may have wildcards. */
8068                 if (dest_has_wild) {
8069                         char *fname_dst_mod = NULL;
8070                         if (!resolve_wildcards(smb_fname_dst,
8071                                                smb_fname_src->base_name,
8072                                                smb_fname_dst->base_name,
8073                                                &fname_dst_mod)) {
8074                                 DEBUG(6, ("rename_internals: resolve_wildcards "
8075                                           "%s %s failed\n",
8076                                           smb_fname_src->base_name,
8077                                           smb_fname_dst->base_name));
8078                                 status = NT_STATUS_NO_MEMORY;
8079                                 goto out;
8080                         }
8081                         TALLOC_FREE(smb_fname_dst->base_name);
8082                         smb_fname_dst->base_name = fname_dst_mod;
8083                 }
8084
8085                 ZERO_STRUCT(smb_fname_src->st);
8086                 if (posix_pathnames) {
8087                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8088                 } else {
8089                         rc = SMB_VFS_STAT(conn, smb_fname_src);
8090                 }
8091                 if (rc == -1) {
8092                         status = map_nt_error_from_unix_common(errno);
8093                         goto out;
8094                 }
8095
8096                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8097                         create_options |= FILE_DIRECTORY_FILE;
8098                 }
8099
8100                 status = SMB_VFS_CREATE_FILE(
8101                         conn,                           /* conn */
8102                         req,                            /* req */
8103                         &conn->cwd_fsp,                 /* dirfsp */
8104                         smb_fname_src,                  /* fname */
8105                         access_mask,                    /* access_mask */
8106                         (FILE_SHARE_READ |              /* share_access */
8107                             FILE_SHARE_WRITE),
8108                         FILE_OPEN,                      /* create_disposition*/
8109                         create_options,                 /* create_options */
8110                         0,                              /* file_attributes */
8111                         0,                              /* oplock_request */
8112                         NULL,                           /* lease */
8113                         0,                              /* allocation_size */
8114                         0,                              /* private_flags */
8115                         NULL,                           /* sd */
8116                         NULL,                           /* ea_list */
8117                         &fsp,                           /* result */
8118                         NULL,                           /* pinfo */
8119                         posx,                           /* in_context_blobs */
8120                         NULL);                          /* out_context_blobs */
8121
8122                 if (!NT_STATUS_IS_OK(status)) {
8123                         DEBUG(3, ("Could not open rename source %s: %s\n",
8124                                   smb_fname_str_dbg(smb_fname_src),
8125                                   nt_errstr(status)));
8126                         goto out;
8127                 }
8128
8129                 status = rename_internals_fsp(conn,
8130                                         fsp,
8131                                         smb_fname_dst,
8132                                         dst_original_lcomp,
8133                                         attrs,
8134                                         replace_if_exists);
8135
8136                 close_file(req, fsp, NORMAL_CLOSE);
8137
8138                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8139                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8140                           smb_fname_str_dbg(smb_fname_dst)));
8141
8142                 goto out;
8143         }
8144
8145         /*
8146          * Wildcards - process each file that matches.
8147          */
8148         if (strequal(fname_src_mask, "????????.???")) {
8149                 TALLOC_FREE(fname_src_mask);
8150                 fname_src_mask = talloc_strdup(ctx, "*");
8151                 if (!fname_src_mask) {
8152                         status = NT_STATUS_NO_MEMORY;
8153                         goto out;
8154                 }
8155         }
8156
8157         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8158                                 fname_src_dir,
8159                                 NULL,
8160                                 NULL,
8161                                 smb_fname_src->twrp,
8162                                 smb_fname_src->flags);
8163         if (smb_fname_src_dir == NULL) {
8164                 status = NT_STATUS_NO_MEMORY;
8165                 goto out;
8166         }
8167
8168         status = check_name(conn, smb_fname_src_dir);
8169         if (!NT_STATUS_IS_OK(status)) {
8170                 goto out;
8171         }
8172
8173         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8174                           attrs);
8175         if (dir_hnd == NULL) {
8176                 status = map_nt_error_from_unix(errno);
8177                 goto out;
8178         }
8179
8180         status = NT_STATUS_NO_SUCH_FILE;
8181         /*
8182          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8183          * - gentest fix. JRA
8184          */
8185
8186         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8187                                     &talloced))) {
8188                 files_struct *fsp = NULL;
8189                 char *destname = NULL;
8190                 bool sysdir_entry = False;
8191
8192                 /* Quick check for "." and ".." */
8193                 if (ISDOT(dname) || ISDOTDOT(dname)) {
8194                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8195                                 sysdir_entry = True;
8196                         } else {
8197                                 TALLOC_FREE(talloced);
8198                                 continue;
8199                         }
8200                 }
8201
8202                 if (!is_visible_file(conn,
8203                                 dir_hnd,
8204                                 dname,
8205                                 &smb_fname_src->st,
8206                                 false)) {
8207                         TALLOC_FREE(talloced);
8208                         continue;
8209                 }
8210
8211                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8212                         TALLOC_FREE(talloced);
8213                         continue;
8214                 }
8215
8216                 if (sysdir_entry) {
8217                         status = NT_STATUS_OBJECT_NAME_INVALID;
8218                         break;
8219                 }
8220
8221                 TALLOC_FREE(smb_fname_src->base_name);
8222                 if (ISDOT(fname_src_dir)) {
8223                         /* Ensure we use canonical names on open. */
8224                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8225                                                         "%s",
8226                                                         dname);
8227                 } else {
8228                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8229                                                         "%s/%s",
8230                                                         fname_src_dir,
8231                                                         dname);
8232                 }
8233                 if (!smb_fname_src->base_name) {
8234                         status = NT_STATUS_NO_MEMORY;
8235                         goto out;
8236                 }
8237
8238                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8239                                        smb_fname_dst->base_name,
8240                                        &destname)) {
8241                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
8242                                   smb_fname_src->base_name, destname));
8243                         TALLOC_FREE(talloced);
8244                         continue;
8245                 }
8246                 if (!destname) {
8247                         status = NT_STATUS_NO_MEMORY;
8248                         goto out;
8249                 }
8250
8251                 TALLOC_FREE(smb_fname_dst->base_name);
8252                 smb_fname_dst->base_name = destname;
8253
8254                 ZERO_STRUCT(smb_fname_src->st);
8255                 if (posix_pathnames) {
8256                         SMB_VFS_LSTAT(conn, smb_fname_src);
8257                 } else {
8258                         SMB_VFS_STAT(conn, smb_fname_src);
8259                 }
8260
8261                 create_options = 0;
8262
8263                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8264                         create_options |= FILE_DIRECTORY_FILE;
8265                 }
8266
8267                 status = SMB_VFS_CREATE_FILE(
8268                         conn,                           /* conn */
8269                         req,                            /* req */
8270                         &conn->cwd_fsp,                 /* dirfsp */
8271                         smb_fname_src,                  /* fname */
8272                         access_mask,                    /* access_mask */
8273                         (FILE_SHARE_READ |              /* share_access */
8274                             FILE_SHARE_WRITE),
8275                         FILE_OPEN,                      /* create_disposition*/
8276                         create_options,                 /* create_options */
8277                         0,                              /* file_attributes */
8278                         0,                              /* oplock_request */
8279                         NULL,                           /* lease */
8280                         0,                              /* allocation_size */
8281                         0,                              /* private_flags */
8282                         NULL,                           /* sd */
8283                         NULL,                           /* ea_list */
8284                         &fsp,                           /* result */
8285                         NULL,                           /* pinfo */
8286                         posx,                           /* in_context_blobs */
8287                         NULL);                          /* out_context_blobs */
8288
8289                 if (!NT_STATUS_IS_OK(status)) {
8290                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8291                                  "returned %s rename %s -> %s\n",
8292                                  nt_errstr(status),
8293                                  smb_fname_str_dbg(smb_fname_src),
8294                                  smb_fname_str_dbg(smb_fname_dst)));
8295                         break;
8296                 }
8297
8298                 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8299                 if (dst_original_lcomp == NULL) {
8300                         status = NT_STATUS_NO_MEMORY;
8301                         goto out;
8302                 }
8303
8304                 status = rename_internals_fsp(conn,
8305                                         fsp,
8306                                         smb_fname_dst,
8307                                         dst_original_lcomp,
8308                                         attrs,
8309                                         replace_if_exists);
8310
8311                 close_file(req, fsp, NORMAL_CLOSE);
8312
8313                 if (!NT_STATUS_IS_OK(status)) {
8314                         DEBUG(3, ("rename_internals_fsp returned %s for "
8315                                   "rename %s -> %s\n", nt_errstr(status),
8316                                   smb_fname_str_dbg(smb_fname_src),
8317                                   smb_fname_str_dbg(smb_fname_dst)));
8318                         break;
8319                 }
8320
8321                 count++;
8322
8323                 DEBUG(3,("rename_internals: doing rename on %s -> "
8324                          "%s\n", smb_fname_str_dbg(smb_fname_src),
8325                          smb_fname_str_dbg(smb_fname_src)));
8326                 TALLOC_FREE(talloced);
8327         }
8328         TALLOC_FREE(dir_hnd);
8329
8330         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8331                 status = map_nt_error_from_unix(errno);
8332         }
8333
8334  out:
8335         TALLOC_FREE(posx);
8336         TALLOC_FREE(talloced);
8337         TALLOC_FREE(smb_fname_src_dir);
8338         TALLOC_FREE(fname_src_dir);
8339         TALLOC_FREE(fname_src_mask);
8340         return status;
8341 }
8342
8343 /****************************************************************************
8344  Reply to a mv.
8345 ****************************************************************************/
8346
8347 void reply_mv(struct smb_request *req)
8348 {
8349         connection_struct *conn = req->conn;
8350         char *name = NULL;
8351         char *newname = NULL;
8352         const char *p;
8353         uint32_t attrs;
8354         NTSTATUS status;
8355         bool src_has_wcard = False;
8356         bool dest_has_wcard = False;
8357         TALLOC_CTX *ctx = talloc_tos();
8358         struct smb_filename *smb_fname_src = NULL;
8359         struct smb_filename *smb_fname_dst = NULL;
8360         const char *dst_original_lcomp = NULL;
8361         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8362                 (req->posix_pathnames ?
8363                         UCF_UNIX_NAME_LOOKUP :
8364                         UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8365         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8366                 (req->posix_pathnames ?
8367                         0 :
8368                         UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8369         bool stream_rename = false;
8370
8371         START_PROFILE(SMBmv);
8372
8373         if (req->wct < 1) {
8374                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8375                 goto out;
8376         }
8377
8378         attrs = SVAL(req->vwv+0, 0);
8379
8380         p = (const char *)req->buf + 1;
8381         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8382                                        &status, &src_has_wcard);
8383         if (!NT_STATUS_IS_OK(status)) {
8384                 reply_nterror(req, status);
8385                 goto out;
8386         }
8387         p++;
8388         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8389                                        &status, &dest_has_wcard);
8390         if (!NT_STATUS_IS_OK(status)) {
8391                 reply_nterror(req, status);
8392                 goto out;
8393         }
8394
8395         if (!req->posix_pathnames) {
8396                 /* The newname must begin with a ':' if the
8397                    name contains a ':'. */
8398                 if (strchr_m(name, ':')) {
8399                         if (newname[0] != ':') {
8400                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8401                                 goto out;
8402                         }
8403                         stream_rename = true;
8404                 }
8405         }
8406
8407         status = filename_convert(ctx,
8408                                   conn,
8409                                   name,
8410                                   src_ucf_flags,
8411                                   0,
8412                                   &src_has_wcard,
8413                                   &smb_fname_src);
8414
8415         if (!NT_STATUS_IS_OK(status)) {
8416                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8417                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8418                                         ERRSRV, ERRbadpath);
8419                         goto out;
8420                 }
8421                 reply_nterror(req, status);
8422                 goto out;
8423         }
8424
8425         status = filename_convert(ctx,
8426                                   conn,
8427                                   newname,
8428                                   dst_ucf_flags,
8429                                   0,
8430                                   &dest_has_wcard,
8431                                   &smb_fname_dst);
8432
8433         if (!NT_STATUS_IS_OK(status)) {
8434                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8435                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8436                                         ERRSRV, ERRbadpath);
8437                         goto out;
8438                 }
8439                 reply_nterror(req, status);
8440                 goto out;
8441         }
8442
8443         /* Get the last component of the destination for rename_internals(). */
8444         dst_original_lcomp = get_original_lcomp(ctx,
8445                                         conn,
8446                                         newname,
8447                                         dst_ucf_flags);
8448         if (dst_original_lcomp == NULL) {
8449                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8450                 goto out;
8451         }
8452
8453         if (stream_rename) {
8454                 /* smb_fname_dst->base_name must be the same as
8455                    smb_fname_src->base_name. */
8456                 TALLOC_FREE(smb_fname_dst->base_name);
8457                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8458                                                 smb_fname_src->base_name);
8459                 if (!smb_fname_dst->base_name) {
8460                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8461                         goto out;
8462                 }
8463         }
8464
8465         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8466                  smb_fname_str_dbg(smb_fname_dst)));
8467
8468         status = rename_internals(ctx,
8469                                 conn,
8470                                 req,
8471                                 smb_fname_src,
8472                                 smb_fname_dst,
8473                                 dst_original_lcomp,
8474                                 attrs,
8475                                 false,
8476                                 src_has_wcard,
8477                                 dest_has_wcard,
8478                                 DELETE_ACCESS);
8479         if (!NT_STATUS_IS_OK(status)) {
8480                 if (open_was_deferred(req->xconn, req->mid)) {
8481                         /* We have re-scheduled this call. */
8482                         goto out;
8483                 }
8484                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8485                         bool ok = defer_smb1_sharing_violation(req);
8486                         if (ok) {
8487                                 goto out;
8488                         }
8489                 }
8490                 reply_nterror(req, status);
8491                 goto out;
8492         }
8493
8494         reply_outbuf(req, 0, 0);
8495  out:
8496         TALLOC_FREE(smb_fname_src);
8497         TALLOC_FREE(smb_fname_dst);
8498         END_PROFILE(SMBmv);
8499         return;
8500 }
8501
8502 /*******************************************************************
8503  Copy a file as part of a reply_copy.
8504 ******************************************************************/
8505
8506 /*
8507  * TODO: check error codes on all callers
8508  */
8509
8510 NTSTATUS copy_file(TALLOC_CTX *ctx,
8511                         connection_struct *conn,
8512                         struct smb_filename *smb_fname_src,
8513                         struct smb_filename *smb_fname_dst,
8514                         int ofun,
8515                         int count,
8516                         bool target_is_directory)
8517 {
8518         struct smb_filename *smb_fname_dst_tmp = NULL;
8519         off_t ret=-1;
8520         files_struct *fsp1,*fsp2;
8521         uint32_t dosattrs;
8522         uint32_t new_create_disposition;
8523         NTSTATUS status;
8524
8525
8526         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8527         if (smb_fname_dst_tmp == NULL) {
8528                 return NT_STATUS_NO_MEMORY;
8529         }
8530
8531         /*
8532          * If the target is a directory, extract the last component from the
8533          * src filename and append it to the dst filename
8534          */
8535         if (target_is_directory) {
8536                 const char *p;
8537
8538                 /* dest/target can't be a stream if it's a directory. */
8539                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8540
8541                 p = strrchr_m(smb_fname_src->base_name,'/');
8542                 if (p) {
8543                         p++;
8544                 } else {
8545                         p = smb_fname_src->base_name;
8546                 }
8547                 smb_fname_dst_tmp->base_name =
8548                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8549                                            p);
8550                 if (!smb_fname_dst_tmp->base_name) {
8551                         status = NT_STATUS_NO_MEMORY;
8552                         goto out;
8553                 }
8554         }
8555
8556         status = vfs_file_exist(conn, smb_fname_src);
8557         if (!NT_STATUS_IS_OK(status)) {
8558                 goto out;
8559         }
8560
8561         if (!target_is_directory && count) {
8562                 new_create_disposition = FILE_OPEN;
8563         } else {
8564                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8565                                                  0, ofun,
8566                                                  NULL, NULL,
8567                                                  &new_create_disposition,
8568                                                  NULL,
8569                                                  NULL)) {
8570                         status = NT_STATUS_INVALID_PARAMETER;
8571                         goto out;
8572                 }
8573         }
8574
8575         /* Open the src file for reading. */
8576         status = SMB_VFS_CREATE_FILE(
8577                 conn,                                   /* conn */
8578                 NULL,                                   /* req */
8579                 &conn->cwd_fsp,                         /* dirfsp */
8580                 smb_fname_src,                          /* fname */
8581                 FILE_GENERIC_READ,                      /* access_mask */
8582                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8583                 FILE_OPEN,                              /* create_disposition*/
8584                 0,                                      /* create_options */
8585                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
8586                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8587                 NULL,                                   /* lease */
8588                 0,                                      /* allocation_size */
8589                 0,                                      /* private_flags */
8590                 NULL,                                   /* sd */
8591                 NULL,                                   /* ea_list */
8592                 &fsp1,                                  /* result */
8593                 NULL,                                   /* psbuf */
8594                 NULL, NULL);                            /* create context */
8595
8596         if (!NT_STATUS_IS_OK(status)) {
8597                 goto out;
8598         }
8599
8600         dosattrs = dos_mode(conn, smb_fname_src);
8601
8602         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8603                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8604         }
8605
8606         /* Open the dst file for writing. */
8607         status = SMB_VFS_CREATE_FILE(
8608                 conn,                                   /* conn */
8609                 NULL,                                   /* req */
8610                 &conn->cwd_fsp,                         /* dirfsp */
8611                 smb_fname_dst,                          /* fname */
8612                 FILE_GENERIC_WRITE,                     /* access_mask */
8613                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8614                 new_create_disposition,                 /* create_disposition*/
8615                 0,                                      /* create_options */
8616                 dosattrs,                               /* file_attributes */
8617                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8618                 NULL,                                   /* lease */
8619                 0,                                      /* allocation_size */
8620                 0,                                      /* private_flags */
8621                 NULL,                                   /* sd */
8622                 NULL,                                   /* ea_list */
8623                 &fsp2,                                  /* result */
8624                 NULL,                                   /* psbuf */
8625                 NULL, NULL);                            /* create context */
8626
8627         if (!NT_STATUS_IS_OK(status)) {
8628                 close_file(NULL, fsp1, ERROR_CLOSE);
8629                 goto out;
8630         }
8631
8632         if (ofun & OPENX_FILE_EXISTS_OPEN) {
8633                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8634                 if (ret == -1) {
8635                         DEBUG(0, ("error - vfs lseek returned error %s\n",
8636                                 strerror(errno)));
8637                         status = map_nt_error_from_unix(errno);
8638                         close_file(NULL, fsp1, ERROR_CLOSE);
8639                         close_file(NULL, fsp2, ERROR_CLOSE);
8640                         goto out;
8641                 }
8642         }
8643
8644         /* Do the actual copy. */
8645         if (smb_fname_src->st.st_ex_size) {
8646                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8647         } else {
8648                 ret = 0;
8649         }
8650
8651         close_file(NULL, fsp1, NORMAL_CLOSE);
8652
8653         /* Ensure the modtime is set correctly on the destination file. */
8654         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8655
8656         /*
8657          * As we are opening fsp1 read-only we only expect
8658          * an error on close on fsp2 if we are out of space.
8659          * Thus we don't look at the error return from the
8660          * close of fsp1.
8661          */
8662         status = close_file(NULL, fsp2, NORMAL_CLOSE);
8663
8664         if (!NT_STATUS_IS_OK(status)) {
8665                 goto out;
8666         }
8667
8668         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8669                 status = NT_STATUS_DISK_FULL;
8670                 goto out;
8671         }
8672
8673         status = NT_STATUS_OK;
8674
8675  out:
8676         TALLOC_FREE(smb_fname_dst_tmp);
8677         return status;
8678 }
8679
8680 /****************************************************************************
8681  Reply to a file copy.
8682 ****************************************************************************/
8683
8684 void reply_copy(struct smb_request *req)
8685 {
8686         connection_struct *conn = req->conn;
8687         struct smb_filename *smb_fname_src = NULL;
8688         struct smb_filename *smb_fname_src_dir = NULL;
8689         struct smb_filename *smb_fname_dst = NULL;
8690         char *fname_src = NULL;
8691         char *fname_dst = NULL;
8692         char *fname_src_mask = NULL;
8693         char *fname_src_dir = NULL;
8694         const char *p;
8695         int count=0;
8696         int error = ERRnoaccess;
8697         int tid2;
8698         int ofun;
8699         int flags;
8700         bool target_is_directory=False;
8701         bool source_has_wild = False;
8702         bool dest_has_wild = False;
8703         NTSTATUS status;
8704         uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8705                 ucf_flags_from_smb_request(req);
8706         uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8707                 ucf_flags_from_smb_request(req);
8708         TALLOC_CTX *ctx = talloc_tos();
8709
8710         START_PROFILE(SMBcopy);
8711
8712         if (req->wct < 3) {
8713                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8714                 goto out;
8715         }
8716
8717         tid2 = SVAL(req->vwv+0, 0);
8718         ofun = SVAL(req->vwv+1, 0);
8719         flags = SVAL(req->vwv+2, 0);
8720
8721         p = (const char *)req->buf;
8722         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8723                                        &status, &source_has_wild);
8724         if (!NT_STATUS_IS_OK(status)) {
8725                 reply_nterror(req, status);
8726                 goto out;
8727         }
8728         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8729                                        &status, &dest_has_wild);
8730         if (!NT_STATUS_IS_OK(status)) {
8731                 reply_nterror(req, status);
8732                 goto out;
8733         }
8734
8735         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8736
8737         if (tid2 != conn->cnum) {
8738                 /* can't currently handle inter share copies XXXX */
8739                 DEBUG(3,("Rejecting inter-share copy\n"));
8740                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8741                 goto out;
8742         }
8743
8744         status = filename_convert(ctx, conn,
8745                                   fname_src,
8746                                   ucf_flags_src,
8747                                   0,
8748                                   &source_has_wild,
8749                                   &smb_fname_src);
8750         if (!NT_STATUS_IS_OK(status)) {
8751                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8752                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8753                                         ERRSRV, ERRbadpath);
8754                         goto out;
8755                 }
8756                 reply_nterror(req, status);
8757                 goto out;
8758         }
8759
8760         status = filename_convert(ctx, conn,
8761                                   fname_dst,
8762                                   ucf_flags_dst,
8763                                   0,
8764                                   &dest_has_wild,
8765                                   &smb_fname_dst);
8766         if (!NT_STATUS_IS_OK(status)) {
8767                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8768                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8769                                         ERRSRV, ERRbadpath);
8770                         goto out;
8771                 }
8772                 reply_nterror(req, status);
8773                 goto out;
8774         }
8775
8776         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8777
8778         if ((flags&1) && target_is_directory) {
8779                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8780                 goto out;
8781         }
8782
8783         if ((flags&2) && !target_is_directory) {
8784                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8785                 goto out;
8786         }
8787
8788         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8789                 /* wants a tree copy! XXXX */
8790                 DEBUG(3,("Rejecting tree copy\n"));
8791                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8792                 goto out;
8793         }
8794
8795         /* Split up the directory from the filename/mask. */
8796         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8797                                       &fname_src_dir, &fname_src_mask);
8798         if (!NT_STATUS_IS_OK(status)) {
8799                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8800                 goto out;
8801         }
8802
8803         /*
8804          * We should only check the mangled cache
8805          * here if unix_convert failed. This means
8806          * that the path in 'mask' doesn't exist
8807          * on the file system and so we need to look
8808          * for a possible mangle. This patch from
8809          * Tine Smukavec <valentin.smukavec@hermes.si>.
8810          */
8811         if (!VALID_STAT(smb_fname_src->st) &&
8812             mangle_is_mangled(fname_src_mask, conn->params)) {
8813                 char *new_mask = NULL;
8814                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8815                                             &new_mask, conn->params);
8816
8817                 /* Use demangled name if one was successfully found. */
8818                 if (new_mask) {
8819                         TALLOC_FREE(fname_src_mask);
8820                         fname_src_mask = new_mask;
8821                 }
8822         }
8823
8824         if (!source_has_wild) {
8825
8826                 /*
8827                  * Only one file needs to be copied. Append the mask back onto
8828                  * the directory.
8829                  */
8830                 TALLOC_FREE(smb_fname_src->base_name);
8831                 if (ISDOT(fname_src_dir)) {
8832                         /* Ensure we use canonical names on open. */
8833                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8834                                                         "%s",
8835                                                         fname_src_mask);
8836                 } else {
8837                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8838                                                         "%s/%s",
8839                                                         fname_src_dir,
8840                                                         fname_src_mask);
8841                 }
8842                 if (!smb_fname_src->base_name) {
8843                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8844                         goto out;
8845                 }
8846
8847                 if (dest_has_wild) {
8848                         char *fname_dst_mod = NULL;
8849                         if (!resolve_wildcards(smb_fname_dst,
8850                                                smb_fname_src->base_name,
8851                                                smb_fname_dst->base_name,
8852                                                &fname_dst_mod)) {
8853                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8854                                 goto out;
8855                         }
8856                         TALLOC_FREE(smb_fname_dst->base_name);
8857                         smb_fname_dst->base_name = fname_dst_mod;
8858                 }
8859
8860                 status = check_name(conn, smb_fname_src);
8861                 if (!NT_STATUS_IS_OK(status)) {
8862                         reply_nterror(req, status);
8863                         goto out;
8864                 }
8865
8866                 status = check_name(conn, smb_fname_dst);
8867                 if (!NT_STATUS_IS_OK(status)) {
8868                         reply_nterror(req, status);
8869                         goto out;
8870                 }
8871
8872                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8873                                    ofun, count, target_is_directory);
8874
8875                 if(!NT_STATUS_IS_OK(status)) {
8876                         reply_nterror(req, status);
8877                         goto out;
8878                 } else {
8879                         count++;
8880                 }
8881         } else {
8882                 struct smb_Dir *dir_hnd = NULL;
8883                 const char *dname = NULL;
8884                 char *talloced = NULL;
8885                 long offset = 0;
8886
8887                 /*
8888                  * There is a wildcard that requires us to actually read the
8889                  * src dir and copy each file matching the mask to the dst.
8890                  * Right now streams won't be copied, but this could
8891                  * presumably be added with a nested loop for reach dir entry.
8892                  */
8893                 SMB_ASSERT(!smb_fname_src->stream_name);
8894                 SMB_ASSERT(!smb_fname_dst->stream_name);
8895
8896                 smb_fname_src->stream_name = NULL;
8897                 smb_fname_dst->stream_name = NULL;
8898
8899                 if (strequal(fname_src_mask,"????????.???")) {
8900                         TALLOC_FREE(fname_src_mask);
8901                         fname_src_mask = talloc_strdup(ctx, "*");
8902                         if (!fname_src_mask) {
8903                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8904                                 goto out;
8905                         }
8906                 }
8907
8908                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8909                                         fname_src_dir,
8910                                         NULL,
8911                                         NULL,
8912                                         smb_fname_src->twrp,
8913                                         smb_fname_src->flags);
8914                 if (smb_fname_src_dir == NULL) {
8915                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8916                         goto out;
8917                 }
8918
8919                 status = check_name(conn, smb_fname_src_dir);
8920                 if (!NT_STATUS_IS_OK(status)) {
8921                         reply_nterror(req, status);
8922                         goto out;
8923                 }
8924
8925                 dir_hnd = OpenDir(ctx,
8926                                 conn,
8927                                 smb_fname_src_dir,
8928                                 fname_src_mask,
8929                                 0);
8930                 if (dir_hnd == NULL) {
8931                         status = map_nt_error_from_unix(errno);
8932                         reply_nterror(req, status);
8933                         goto out;
8934                 }
8935
8936                 error = ERRbadfile;
8937
8938                 /* Iterate over the src dir copying each entry to the dst. */
8939                 while ((dname = ReadDirName(dir_hnd, &offset,
8940                                             &smb_fname_src->st, &talloced))) {
8941                         char *destname = NULL;
8942
8943                         if (ISDOT(dname) || ISDOTDOT(dname)) {
8944                                 TALLOC_FREE(talloced);
8945                                 continue;
8946                         }
8947
8948                         if (!is_visible_file(conn,
8949                                         dir_hnd,
8950                                         dname,
8951                                         &smb_fname_src->st,
8952                                         false)) {
8953                                 TALLOC_FREE(talloced);
8954                                 continue;
8955                         }
8956
8957                         if(!mask_match(dname, fname_src_mask,
8958                                        conn->case_sensitive)) {
8959                                 TALLOC_FREE(talloced);
8960                                 continue;
8961                         }
8962
8963                         error = ERRnoaccess;
8964
8965                         /* Get the src smb_fname struct setup. */
8966                         TALLOC_FREE(smb_fname_src->base_name);
8967                         if (ISDOT(fname_src_dir)) {
8968                                 /* Ensure we use canonical names on open. */
8969                                 smb_fname_src->base_name =
8970                                         talloc_asprintf(smb_fname_src, "%s",
8971                                                 dname);
8972                         } else {
8973                                 smb_fname_src->base_name =
8974                                         talloc_asprintf(smb_fname_src, "%s/%s",
8975                                                 fname_src_dir, dname);
8976                         }
8977
8978                         if (!smb_fname_src->base_name) {
8979                                 TALLOC_FREE(dir_hnd);
8980                                 TALLOC_FREE(talloced);
8981                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8982                                 goto out;
8983                         }
8984
8985                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8986                                                smb_fname_dst->base_name,
8987                                                &destname)) {
8988                                 TALLOC_FREE(talloced);
8989                                 continue;
8990                         }
8991                         if (!destname) {
8992                                 TALLOC_FREE(dir_hnd);
8993                                 TALLOC_FREE(talloced);
8994                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8995                                 goto out;
8996                         }
8997
8998                         TALLOC_FREE(smb_fname_dst->base_name);
8999                         smb_fname_dst->base_name = destname;
9000
9001                         status = check_name(conn, smb_fname_src);
9002                         if (!NT_STATUS_IS_OK(status)) {
9003                                 TALLOC_FREE(dir_hnd);
9004                                 TALLOC_FREE(talloced);
9005                                 reply_nterror(req, status);
9006                                 goto out;
9007                         }
9008
9009                         status = check_name(conn, smb_fname_dst);
9010                         if (!NT_STATUS_IS_OK(status)) {
9011                                 TALLOC_FREE(dir_hnd);
9012                                 TALLOC_FREE(talloced);
9013                                 reply_nterror(req, status);
9014                                 goto out;
9015                         }
9016
9017                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9018                                 smb_fname_src->base_name,
9019                                 smb_fname_dst->base_name));
9020
9021                         status = copy_file(ctx, conn, smb_fname_src,
9022                                            smb_fname_dst, ofun, count,
9023                                            target_is_directory);
9024                         if (NT_STATUS_IS_OK(status)) {
9025                                 count++;
9026                         }
9027
9028                         TALLOC_FREE(talloced);
9029                 }
9030                 TALLOC_FREE(dir_hnd);
9031         }
9032
9033         if (count == 0) {
9034                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9035                 goto out;
9036         }
9037
9038         reply_outbuf(req, 1, 0);
9039         SSVAL(req->outbuf,smb_vwv0,count);
9040  out:
9041         TALLOC_FREE(smb_fname_src);
9042         TALLOC_FREE(smb_fname_src_dir);
9043         TALLOC_FREE(smb_fname_dst);
9044         TALLOC_FREE(fname_src);
9045         TALLOC_FREE(fname_dst);
9046         TALLOC_FREE(fname_src_mask);
9047         TALLOC_FREE(fname_src_dir);
9048
9049         END_PROFILE(SMBcopy);
9050         return;
9051 }
9052
9053 #undef DBGC_CLASS
9054 #define DBGC_CLASS DBGC_LOCKING
9055
9056 /****************************************************************************
9057  Get a lock pid, dealing with large count requests.
9058 ****************************************************************************/
9059
9060 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9061                     bool large_file_format)
9062 {
9063         if(!large_file_format)
9064                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9065         else
9066                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9067 }
9068
9069 /****************************************************************************
9070  Get a lock count, dealing with large count requests.
9071 ****************************************************************************/
9072
9073 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9074                         bool large_file_format)
9075 {
9076         uint64_t count = 0;
9077
9078         if(!large_file_format) {
9079                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9080         } else {
9081                 /*
9082                  * No BVAL, this is reversed!
9083                  */
9084                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9085                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9086         }
9087
9088         return count;
9089 }
9090
9091 /****************************************************************************
9092  Get a lock offset, dealing with large offset requests.
9093 ****************************************************************************/
9094
9095 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9096                          bool large_file_format)
9097 {
9098         uint64_t offset = 0;
9099
9100         if(!large_file_format) {
9101                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9102         } else {
9103                 /*
9104                  * No BVAL, this is reversed!
9105                  */
9106                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9107                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9108         }
9109
9110         return offset;
9111 }
9112
9113 struct smbd_do_unlocking_state {
9114         struct files_struct *fsp;
9115         uint16_t num_ulocks;
9116         struct smbd_lock_element *ulocks;
9117         enum brl_flavour lock_flav;
9118         NTSTATUS status;
9119 };
9120
9121 static void smbd_do_unlocking_fn(
9122         const uint8_t *buf,
9123         size_t buflen,
9124         bool *pmodified_dependent,
9125         void *private_data)
9126 {
9127         struct smbd_do_unlocking_state *state = private_data;
9128         struct files_struct *fsp = state->fsp;
9129         enum brl_flavour lock_flav = state->lock_flav;
9130         uint16_t i;
9131
9132         for (i = 0; i < state->num_ulocks; i++) {
9133                 struct smbd_lock_element *e = &state->ulocks[i];
9134
9135                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9136                           "pid %"PRIu64", file %s\n",
9137                           e->offset,
9138                           e->count,
9139                           e->smblctx,
9140                           fsp_str_dbg(fsp));
9141
9142                 if (e->brltype != UNLOCK_LOCK) {
9143                         /* this can only happen with SMB2 */
9144                         state->status = NT_STATUS_INVALID_PARAMETER;
9145                         return;
9146                 }
9147
9148                 state->status = do_unlock(
9149                         fsp, e->smblctx, e->count, e->offset, lock_flav);
9150
9151                 DBG_DEBUG("do_unlock returned %s\n",
9152                           nt_errstr(state->status));
9153
9154                 if (!NT_STATUS_IS_OK(state->status)) {
9155                         return;
9156                 }
9157         }
9158
9159         *pmodified_dependent = true;
9160 }
9161
9162 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9163                            files_struct *fsp,
9164                            uint16_t num_ulocks,
9165                            struct smbd_lock_element *ulocks,
9166                            enum brl_flavour lock_flav)
9167 {
9168         struct smbd_do_unlocking_state state = {
9169                 .fsp = fsp,
9170                 .num_ulocks = num_ulocks,
9171                 .ulocks = ulocks,
9172                 .lock_flav = lock_flav,
9173         };
9174         NTSTATUS status;
9175
9176         DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9177
9178         status = share_mode_do_locked(
9179                 fsp->file_id, smbd_do_unlocking_fn, &state);
9180
9181         if (!NT_STATUS_IS_OK(status)) {
9182                 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9183                           nt_errstr(status));
9184                 return status;
9185         }
9186         if (!NT_STATUS_IS_OK(state.status)) {
9187                 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9188                           nt_errstr(status));
9189                 return state.status;
9190         }
9191
9192         return NT_STATUS_OK;
9193 }
9194
9195 /****************************************************************************
9196  Reply to a lockingX request.
9197 ****************************************************************************/
9198
9199 static void reply_lockingx_done(struct tevent_req *subreq);
9200
9201 void reply_lockingX(struct smb_request *req)
9202 {
9203         connection_struct *conn = req->conn;
9204         files_struct *fsp;
9205         unsigned char locktype;
9206         enum brl_type brltype;
9207         unsigned char oplocklevel;
9208         uint16_t num_ulocks;
9209         uint16_t num_locks;
9210         int32_t lock_timeout;
9211         uint16_t i;
9212         const uint8_t *data;
9213         bool large_file_format;
9214         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9215         struct smbd_lock_element *locks = NULL;
9216         struct tevent_req *subreq = NULL;
9217
9218         START_PROFILE(SMBlockingX);
9219
9220         if (req->wct < 8) {
9221                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9222                 END_PROFILE(SMBlockingX);
9223                 return;
9224         }
9225
9226         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9227         locktype = CVAL(req->vwv+3, 0);
9228         oplocklevel = CVAL(req->vwv+3, 1);
9229         num_ulocks = SVAL(req->vwv+6, 0);
9230         num_locks = SVAL(req->vwv+7, 0);
9231         lock_timeout = IVAL(req->vwv+4, 0);
9232         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9233
9234         if (!check_fsp(conn, req, fsp)) {
9235                 END_PROFILE(SMBlockingX);
9236                 return;
9237         }
9238
9239         data = req->buf;
9240
9241         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9242                 /* we don't support these - and CANCEL_LOCK makes w2k
9243                    and XP reboot so I don't really want to be
9244                    compatible! (tridge) */
9245                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9246                 END_PROFILE(SMBlockingX);
9247                 return;
9248         }
9249
9250         /* Check if this is an oplock break on a file
9251            we have granted an oplock on.
9252         */
9253         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9254                 /* Client can insist on breaking to none. */
9255                 bool break_to_none = (oplocklevel == 0);
9256                 bool result;
9257
9258                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9259                          "for %s\n", (unsigned int)oplocklevel,
9260                          fsp_fnum_dbg(fsp)));
9261
9262                 /*
9263                  * Make sure we have granted an exclusive or batch oplock on
9264                  * this file.
9265                  */
9266
9267                 if (fsp->oplock_type == 0) {
9268
9269                         /* The Samba4 nbench simulator doesn't understand
9270                            the difference between break to level2 and break
9271                            to none from level2 - it sends oplock break
9272                            replies in both cases. Don't keep logging an error
9273                            message here - just ignore it. JRA. */
9274
9275                         DEBUG(5,("reply_lockingX: Error : oplock break from "
9276                                  "client for %s (oplock=%d) and no "
9277                                  "oplock granted on this file (%s).\n",
9278                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
9279                                  fsp_str_dbg(fsp)));
9280
9281                         /* if this is a pure oplock break request then don't
9282                          * send a reply */
9283                         if (num_locks == 0 && num_ulocks == 0) {
9284                                 END_PROFILE(SMBlockingX);
9285                                 return;
9286                         }
9287
9288                         END_PROFILE(SMBlockingX);
9289                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9290                         return;
9291                 }
9292
9293                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9294                     (break_to_none)) {
9295                         result = remove_oplock(fsp);
9296                 } else {
9297                         result = downgrade_oplock(fsp);
9298                 }
9299
9300                 if (!result) {
9301                         DEBUG(0, ("reply_lockingX: error in removing "
9302                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
9303                         /* Hmmm. Is this panic justified? */
9304                         smb_panic("internal tdb error");
9305                 }
9306
9307                 /* if this is a pure oplock break request then don't send a
9308                  * reply */
9309                 if (num_locks == 0 && num_ulocks == 0) {
9310                         /* Sanity check - ensure a pure oplock break is not a
9311                            chained request. */
9312                         if (CVAL(req->vwv+0, 0) != 0xff) {
9313                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
9314                                          "break is a chained %d request !\n",
9315                                          (unsigned int)CVAL(req->vwv+0, 0)));
9316                         }
9317                         END_PROFILE(SMBlockingX);
9318                         return;
9319                 }
9320         }
9321
9322         if (req->buflen <
9323             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9324                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9325                 END_PROFILE(SMBlockingX);
9326                 return;
9327         }
9328
9329         if (num_ulocks != 0) {
9330                 struct smbd_lock_element *ulocks = NULL;
9331                 bool ok;
9332
9333                 ulocks = talloc_array(
9334                         req, struct smbd_lock_element, num_ulocks);
9335                 if (ulocks == NULL) {
9336                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9337                         END_PROFILE(SMBlockingX);
9338                         return;
9339                 }
9340
9341                 /*
9342                  * Data now points at the beginning of the list of
9343                  * smb_unlkrng structs
9344                  */
9345                 for (i = 0; i < num_ulocks; i++) {
9346                         ulocks[i].req_guid = smbd_request_guid(req,
9347                                 UINT16_MAX - i),
9348                         ulocks[i].smblctx = get_lock_pid(
9349                                 data, i, large_file_format);
9350                         ulocks[i].count = get_lock_count(
9351                                 data, i, large_file_format);
9352                         ulocks[i].offset = get_lock_offset(
9353                                 data, i, large_file_format);
9354                         ulocks[i].brltype = UNLOCK_LOCK;
9355                 }
9356
9357                 /*
9358                  * Unlock cancels pending locks
9359                  */
9360
9361                 ok = smbd_smb1_brl_finish_by_lock(
9362                         fsp,
9363                         large_file_format,
9364                         WINDOWS_LOCK,
9365                         ulocks[0],
9366                         NT_STATUS_OK);
9367                 if (ok) {
9368                         reply_outbuf(req, 2, 0);
9369                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9370                         SSVAL(req->outbuf, smb_vwv1, 0);
9371                         END_PROFILE(SMBlockingX);
9372                         return;
9373                 }
9374
9375                 status = smbd_do_unlocking(
9376                         req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9377                 TALLOC_FREE(ulocks);
9378                 if (!NT_STATUS_IS_OK(status)) {
9379                         END_PROFILE(SMBlockingX);
9380                         reply_nterror(req, status);
9381                         return;
9382                 }
9383         }
9384
9385         /* Now do any requested locks */
9386         data += ((large_file_format ? 20 : 10)*num_ulocks);
9387
9388         /* Data now points at the beginning of the list
9389            of smb_lkrng structs */
9390
9391         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9392                 brltype = READ_LOCK;
9393         } else {
9394                 brltype = WRITE_LOCK;
9395         }
9396
9397         locks = talloc_array(req, struct smbd_lock_element, num_locks);
9398         if (locks == NULL) {
9399                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9400                 END_PROFILE(SMBlockingX);
9401                 return;
9402         }
9403
9404         for (i = 0; i < num_locks; i++) {
9405                 locks[i].req_guid = smbd_request_guid(req, i),
9406                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9407                 locks[i].count = get_lock_count(data, i, large_file_format);
9408                 locks[i].offset = get_lock_offset(data, i, large_file_format);
9409                 locks[i].brltype = brltype;
9410         }
9411
9412         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9413
9414                 bool ok;
9415
9416                 if (num_locks == 0) {
9417                         /* See smbtorture3 lock11 test */
9418                         reply_outbuf(req, 2, 0);
9419                         /* andx chain ends */
9420                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9421                         SSVAL(req->outbuf, smb_vwv1, 0);
9422                         END_PROFILE(SMBlockingX);
9423                         return;
9424                 }
9425
9426                 ok = smbd_smb1_brl_finish_by_lock(
9427                         fsp,
9428                         large_file_format,
9429                         WINDOWS_LOCK,
9430                         locks[0], /* Windows only cancels the first lock */
9431                         NT_STATUS_FILE_LOCK_CONFLICT);
9432
9433                 if (!ok) {
9434                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9435                         END_PROFILE(SMBlockingX);
9436                         return;
9437                 }
9438
9439                 reply_outbuf(req, 2, 0);
9440                 SSVAL(req->outbuf, smb_vwv0, 0xff);
9441                 SSVAL(req->outbuf, smb_vwv1, 0);
9442                 END_PROFILE(SMBlockingX);
9443                 return;
9444         }
9445
9446         subreq = smbd_smb1_do_locks_send(
9447                 fsp,
9448                 req->sconn->ev_ctx,
9449                 &req,
9450                 fsp,
9451                 lock_timeout,
9452                 large_file_format,
9453                 WINDOWS_LOCK,
9454                 num_locks,
9455                 locks);
9456         if (subreq == NULL) {
9457                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9458                 END_PROFILE(SMBlockingX);
9459                 return;
9460         }
9461         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9462         END_PROFILE(SMBlockingX);
9463 }
9464
9465 static void reply_lockingx_done(struct tevent_req *subreq)
9466 {
9467         struct smb_request *req = NULL;
9468         NTSTATUS status;
9469         bool ok;
9470
9471         START_PROFILE(SMBlockingX);
9472
9473         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9474         SMB_ASSERT(ok);
9475
9476         status = smbd_smb1_do_locks_recv(subreq);
9477         TALLOC_FREE(subreq);
9478
9479         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9480
9481         if (NT_STATUS_IS_OK(status)) {
9482                 reply_outbuf(req, 2, 0);
9483                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9484                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
9485         } else {
9486                 reply_nterror(req, status);
9487         }
9488
9489         ok = srv_send_smb(req->xconn,
9490                           (char *)req->outbuf,
9491                           true,
9492                           req->seqnum+1,
9493                           IS_CONN_ENCRYPTED(req->conn),
9494                           NULL);
9495         if (!ok) {
9496                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9497         }
9498         TALLOC_FREE(req);
9499         END_PROFILE(SMBlockingX);
9500 }
9501
9502 #undef DBGC_CLASS
9503 #define DBGC_CLASS DBGC_ALL
9504
9505 /****************************************************************************
9506  Reply to a SMBreadbmpx (read block multiplex) request.
9507  Always reply with an error, if someone has a platform really needs this,
9508  please contact vl@samba.org
9509 ****************************************************************************/
9510
9511 void reply_readbmpx(struct smb_request *req)
9512 {
9513         START_PROFILE(SMBreadBmpx);
9514         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9515         END_PROFILE(SMBreadBmpx);
9516         return;
9517 }
9518
9519 /****************************************************************************
9520  Reply to a SMBreadbs (read block multiplex secondary) request.
9521  Always reply with an error, if someone has a platform really needs this,
9522  please contact vl@samba.org
9523 ****************************************************************************/
9524
9525 void reply_readbs(struct smb_request *req)
9526 {
9527         START_PROFILE(SMBreadBs);
9528         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9529         END_PROFILE(SMBreadBs);
9530         return;
9531 }
9532
9533 /****************************************************************************
9534  Reply to a SMBsetattrE.
9535 ****************************************************************************/
9536
9537 void reply_setattrE(struct smb_request *req)
9538 {
9539         connection_struct *conn = req->conn;
9540         struct smb_file_time ft;
9541         files_struct *fsp;
9542         NTSTATUS status;
9543
9544         START_PROFILE(SMBsetattrE);
9545         init_smb_file_time(&ft);
9546
9547         if (req->wct < 7) {
9548                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9549                 goto out;
9550         }
9551
9552         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9553
9554         if(!fsp || (fsp->conn != conn)) {
9555                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9556                 goto out;
9557         }
9558
9559         /*
9560          * Convert the DOS times into unix times.
9561          */
9562
9563         ft.atime = time_t_to_full_timespec(
9564             srv_make_unix_date2(req->vwv+3));
9565         ft.mtime = time_t_to_full_timespec(
9566             srv_make_unix_date2(req->vwv+5));
9567         ft.create_time = time_t_to_full_timespec(
9568             srv_make_unix_date2(req->vwv+1));
9569
9570         reply_outbuf(req, 0, 0);
9571
9572         /* 
9573          * Patch from Ray Frush <frush@engr.colostate.edu>
9574          * Sometimes times are sent as zero - ignore them.
9575          */
9576
9577         /* Ensure we have a valid stat struct for the source. */
9578         status = vfs_stat_fsp(fsp);
9579         if (!NT_STATUS_IS_OK(status)) {
9580                 reply_nterror(req, status);
9581                 goto out;
9582         }
9583
9584         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9585                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9586                 goto out;
9587         }
9588
9589         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9590         if (!NT_STATUS_IS_OK(status)) {
9591                 reply_nterror(req, status);
9592                 goto out;
9593         }
9594
9595         if (fsp->fsp_flags.modified) {
9596                 trigger_write_time_update_immediate(fsp);
9597         }
9598
9599         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9600                " createtime=%u\n",
9601                 fsp_fnum_dbg(fsp),
9602                 (unsigned int)ft.atime.tv_sec,
9603                 (unsigned int)ft.mtime.tv_sec,
9604                 (unsigned int)ft.create_time.tv_sec
9605                 ));
9606  out:
9607         END_PROFILE(SMBsetattrE);
9608         return;
9609 }
9610
9611
9612 /* Back from the dead for OS/2..... JRA. */
9613
9614 /****************************************************************************
9615  Reply to a SMBwritebmpx (write block multiplex primary) request.
9616  Always reply with an error, if someone has a platform really needs this,
9617  please contact vl@samba.org
9618 ****************************************************************************/
9619
9620 void reply_writebmpx(struct smb_request *req)
9621 {
9622         START_PROFILE(SMBwriteBmpx);
9623         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9624         END_PROFILE(SMBwriteBmpx);
9625         return;
9626 }
9627
9628 /****************************************************************************
9629  Reply to a SMBwritebs (write block multiplex secondary) request.
9630  Always reply with an error, if someone has a platform really needs this,
9631  please contact vl@samba.org
9632 ****************************************************************************/
9633
9634 void reply_writebs(struct smb_request *req)
9635 {
9636         START_PROFILE(SMBwriteBs);
9637         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9638         END_PROFILE(SMBwriteBs);
9639         return;
9640 }
9641
9642 /****************************************************************************
9643  Reply to a SMBgetattrE.
9644 ****************************************************************************/
9645
9646 void reply_getattrE(struct smb_request *req)
9647 {
9648         connection_struct *conn = req->conn;
9649         int mode;
9650         files_struct *fsp;
9651         struct timespec create_ts;
9652         NTSTATUS status;
9653
9654         START_PROFILE(SMBgetattrE);
9655
9656         if (req->wct < 1) {
9657                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9658                 END_PROFILE(SMBgetattrE);
9659                 return;
9660         }
9661
9662         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9663
9664         if(!fsp || (fsp->conn != conn)) {
9665                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9666                 END_PROFILE(SMBgetattrE);
9667                 return;
9668         }
9669
9670         /* Do an fstat on this file */
9671         status = vfs_stat_fsp(fsp);
9672         if (!NT_STATUS_IS_OK(status)) {
9673                 reply_nterror(req, status);
9674                 END_PROFILE(SMBgetattrE);
9675                 return;
9676         }
9677
9678         mode = dos_mode(conn, fsp->fsp_name);
9679
9680         /*
9681          * Convert the times into dos times. Set create
9682          * date to be last modify date as UNIX doesn't save
9683          * this.
9684          */
9685
9686         reply_outbuf(req, 11, 0);
9687
9688         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9689         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9690         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9691                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9692         /* Should we check pending modtime here ? JRA */
9693         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9694                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9695
9696         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9697                 SIVAL(req->outbuf, smb_vwv6, 0);
9698                 SIVAL(req->outbuf, smb_vwv8, 0);
9699         } else {
9700                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9701                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9702                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9703         }
9704         SSVAL(req->outbuf,smb_vwv10, mode);
9705
9706         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9707
9708         END_PROFILE(SMBgetattrE);
9709         return;
9710 }