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