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