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