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