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