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