2fa1d9f5dd1d19479f166b23d35fb88e39ad2e69
[amitay/samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
50
51 /****************************************************************************
52  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
53  path or anything including wildcards.
54  We're assuming here that '/' is not the second byte in any multibyte char
55  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
56  set.
57 ****************************************************************************/
58
59 /* Custom version for processing POSIX paths. */
60 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
61
62 static NTSTATUS check_path_syntax_internal(char *path,
63                                            bool posix_path,
64                                            bool *p_last_component_contains_wcard)
65 {
66         char *d = path;
67         const char *s = path;
68         NTSTATUS ret = NT_STATUS_OK;
69         bool start_of_name_component = True;
70         bool stream_started = false;
71
72         *p_last_component_contains_wcard = False;
73
74         while (*s) {
75                 if (stream_started) {
76                         switch (*s) {
77                         case '/':
78                         case '\\':
79                                 return NT_STATUS_OBJECT_NAME_INVALID;
80                         case ':':
81                                 if (s[1] == '\0') {
82                                         return NT_STATUS_OBJECT_NAME_INVALID;
83                                 }
84                                 if (strchr_m(&s[1], ':')) {
85                                         return NT_STATUS_OBJECT_NAME_INVALID;
86                                 }
87                                 break;
88                         }
89                 }
90
91                 if ((*s == ':') && !posix_path && !stream_started) {
92                         if (*p_last_component_contains_wcard) {
93                                 return NT_STATUS_OBJECT_NAME_INVALID;
94                         }
95                         /* Stream names allow more characters than file names.
96                            We're overloading posix_path here to allow a wider
97                            range of characters. If stream_started is true this
98                            is still a Windows path even if posix_path is true.
99                            JRA.
100                         */
101                         stream_started = true;
102                         start_of_name_component = false;
103                         posix_path = true;
104
105                         if (s[1] == '\0') {
106                                 return NT_STATUS_OBJECT_NAME_INVALID;
107                         }
108                 }
109
110                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
111                         /*
112                          * Safe to assume is not the second part of a mb char
113                          * as this is handled below.
114                          */
115                         /* Eat multiple '/' or '\\' */
116                         while (IS_PATH_SEP(*s,posix_path)) {
117                                 s++;
118                         }
119                         if ((d != path) && (*s != '\0')) {
120                                 /* We only care about non-leading or trailing '/' or '\\' */
121                                 *d++ = '/';
122                         }
123
124                         start_of_name_component = True;
125                         /* New component. */
126                         *p_last_component_contains_wcard = False;
127                         continue;
128                 }
129
130                 if (start_of_name_component) {
131                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
133
134                                 /*
135                                  * No mb char starts with '.' so we're safe checking the directory separator here.
136                                  */
137
138                                 /* If  we just added a '/' - delete it */
139                                 if ((d > path) && (*(d-1) == '/')) {
140                                         *(d-1) = '\0';
141                                         d--;
142                                 }
143
144                                 /* Are we at the start ? Can't go back further if so. */
145                                 if (d <= path) {
146                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
147                                         break;
148                                 }
149                                 /* Go back one level... */
150                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
151                                 /* NOTE - if this assumption is invalid we are not in good shape... */
152                                 /* Decrement d first as d points to the *next* char to write into. */
153                                 for (d--; d > path; d--) {
154                                         if (*d == '/')
155                                                 break;
156                                 }
157                                 s += 2; /* Else go past the .. */
158                                 /* We're still at the start of a name component, just the previous one. */
159                                 continue;
160
161                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
162                                 if (posix_path) {
163                                         /* Eat the '.' */
164                                         s++;
165                                         continue;
166                                 }
167                         }
168
169                 }
170
171                 if (!(*s & 0x80)) {
172                         if (!posix_path) {
173                                 if (*s <= 0x1f || *s == '|') {
174                                         return NT_STATUS_OBJECT_NAME_INVALID;
175                                 }
176                                 switch (*s) {
177                                         case '*':
178                                         case '?':
179                                         case '<':
180                                         case '>':
181                                         case '"':
182                                                 *p_last_component_contains_wcard = True;
183                                                 break;
184                                         default:
185                                                 break;
186                                 }
187                         }
188                         *d++ = *s++;
189                 } else {
190                         size_t siz;
191                         /* Get the size of the next MB character. */
192                         next_codepoint(s,&siz);
193                         switch(siz) {
194                                 case 5:
195                                         *d++ = *s++;
196                                         FALL_THROUGH;
197                                 case 4:
198                                         *d++ = *s++;
199                                         FALL_THROUGH;
200                                 case 3:
201                                         *d++ = *s++;
202                                         FALL_THROUGH;
203                                 case 2:
204                                         *d++ = *s++;
205                                         FALL_THROUGH;
206                                 case 1:
207                                         *d++ = *s++;
208                                         break;
209                                 default:
210                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211                                         *d = '\0';
212                                         return NT_STATUS_INVALID_PARAMETER;
213                         }
214                 }
215                 start_of_name_component = False;
216         }
217
218         *d = '\0';
219
220         return ret;
221 }
222
223 /****************************************************************************
224  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225  No wildcards allowed.
226 ****************************************************************************/
227
228 NTSTATUS check_path_syntax(char *path)
229 {
230         bool ignore;
231         return check_path_syntax_internal(path, False, &ignore);
232 }
233
234 /****************************************************************************
235  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
236  Wildcards allowed - p_contains_wcard returns true if the last component contained
237  a wildcard.
238 ****************************************************************************/
239
240 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
241 {
242         return check_path_syntax_internal(path, False, p_contains_wcard);
243 }
244
245 /****************************************************************************
246  Check the path for a POSIX client.
247  We're assuming here that '/' is not the second byte in any multibyte char
248  set (a safe assumption).
249 ****************************************************************************/
250
251 NTSTATUS check_path_syntax_posix(char *path)
252 {
253         bool ignore;
254         return check_path_syntax_internal(path, True, &ignore);
255 }
256
257 /****************************************************************************
258  Pull a string and check the path allowing a wildcard - provide for error return.
259  Passes in posix flag.
260 ****************************************************************************/
261
262 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
263                         const char *base_ptr,
264                         uint16_t smb_flags2,
265                         char **pp_dest,
266                         const char *src,
267                         size_t src_len,
268                         int flags,
269                         bool posix_pathnames,
270                         NTSTATUS *err,
271                         bool *contains_wcard)
272 {
273         size_t ret;
274
275         *pp_dest = NULL;
276
277         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278                                  src_len, flags);
279
280         if (!*pp_dest) {
281                 *err = NT_STATUS_INVALID_PARAMETER;
282                 return ret;
283         }
284
285         *contains_wcard = False;
286
287         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
288                 /*
289                  * For a DFS path the function parse_dfs_path()
290                  * will do the path processing, just make a copy.
291                  */
292                 *err = NT_STATUS_OK;
293                 return ret;
294         }
295
296         if (posix_pathnames) {
297                 *err = check_path_syntax_posix(*pp_dest);
298         } else {
299                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
300         }
301
302         return ret;
303 }
304
305 /****************************************************************************
306  Pull a string and check the path allowing a wildcard - provide for error return.
307 ****************************************************************************/
308
309 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
310                         const char *base_ptr,
311                         uint16_t smb_flags2,
312                         char **pp_dest,
313                         const char *src,
314                         size_t src_len,
315                         int flags,
316                         NTSTATUS *err,
317                         bool *contains_wcard)
318 {
319         return srvstr_get_path_wcard_internal(ctx,
320                         base_ptr,
321                         smb_flags2,
322                         pp_dest,
323                         src,
324                         src_len,
325                         flags,
326                         false,
327                         err,
328                         contains_wcard);
329 }
330
331 /****************************************************************************
332  Pull a string and check the path allowing a wildcard - provide for error return.
333  posix_pathnames version.
334 ****************************************************************************/
335
336 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
337                         const char *base_ptr,
338                         uint16_t smb_flags2,
339                         char **pp_dest,
340                         const char *src,
341                         size_t src_len,
342                         int flags,
343                         NTSTATUS *err,
344                         bool *contains_wcard)
345 {
346         return srvstr_get_path_wcard_internal(ctx,
347                         base_ptr,
348                         smb_flags2,
349                         pp_dest,
350                         src,
351                         src_len,
352                         flags,
353                         true,
354                         err,
355                         contains_wcard);
356 }
357
358 /****************************************************************************
359  Pull a string and check the path - provide for error return.
360 ****************************************************************************/
361
362 size_t srvstr_get_path(TALLOC_CTX *ctx,
363                         const char *base_ptr,
364                         uint16_t smb_flags2,
365                         char **pp_dest,
366                         const char *src,
367                         size_t src_len,
368                         int flags,
369                         NTSTATUS *err)
370 {
371         bool ignore;
372         return srvstr_get_path_wcard_internal(ctx,
373                         base_ptr,
374                         smb_flags2,
375                         pp_dest,
376                         src,
377                         src_len,
378                         flags,
379                         false,
380                         err,
381                         &ignore);
382 }
383
384 /****************************************************************************
385  Pull a string and check the path - provide for error return.
386  posix_pathnames version.
387 ****************************************************************************/
388
389 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
390                         const char *base_ptr,
391                         uint16_t smb_flags2,
392                         char **pp_dest,
393                         const char *src,
394                         size_t src_len,
395                         int flags,
396                         NTSTATUS *err)
397 {
398         bool ignore;
399         return srvstr_get_path_wcard_internal(ctx,
400                         base_ptr,
401                         smb_flags2,
402                         pp_dest,
403                         src,
404                         src_len,
405                         flags,
406                         true,
407                         err,
408                         &ignore);
409 }
410
411
412 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
413                                  char **pp_dest, const char *src, int flags,
414                                  NTSTATUS *err, bool *contains_wcard)
415 {
416         ssize_t bufrem = smbreq_bufrem(req, src);
417
418         if (bufrem < 0) {
419                 *err = NT_STATUS_INVALID_PARAMETER;
420                 return 0;
421         }
422
423         if (req->posix_pathnames) {
424                 return srvstr_get_path_wcard_internal(mem_ctx,
425                                 (const char *)req->inbuf,
426                                 req->flags2,
427                                 pp_dest,
428                                 src,
429                                 bufrem,
430                                 flags,
431                                 true,
432                                 err,
433                                 contains_wcard);
434         } else {
435                 return srvstr_get_path_wcard_internal(mem_ctx,
436                                 (const char *)req->inbuf,
437                                 req->flags2,
438                                 pp_dest,
439                                 src,
440                                 bufrem,
441                                 flags,
442                                 false,
443                                 err,
444                                 contains_wcard);
445         }
446 }
447
448 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
449                            char **pp_dest, const char *src, int flags,
450                            NTSTATUS *err)
451 {
452         bool ignore;
453         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
454                                          flags, err, &ignore);
455 }
456
457 /**
458  * pull a string from the smb_buf part of a packet. In this case the
459  * string can either be null terminated or it can be terminated by the
460  * end of the smbbuf area
461  */
462 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
463                               char **dest, const uint8_t *src, int flags)
464 {
465         ssize_t bufrem = smbreq_bufrem(req, src);
466
467         if (bufrem < 0) {
468                 return 0;
469         }
470
471         return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472                                   bufrem, flags);
473 }
474
475 /****************************************************************************
476  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
477 ****************************************************************************/
478
479 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
480                     files_struct *fsp)
481 {
482         if ((fsp == NULL) || (conn == NULL)) {
483                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
484                 return False;
485         }
486         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
487                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
488                 return False;
489         }
490         return True;
491 }
492
493 /****************************************************************************
494  Check if we have a correct fsp pointing to a file.
495 ****************************************************************************/
496
497 bool check_fsp(connection_struct *conn, struct smb_request *req,
498                files_struct *fsp)
499 {
500         if (!check_fsp_open(conn, req, fsp)) {
501                 return False;
502         }
503         if (fsp->fsp_flags.is_directory) {
504                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
505                 return False;
506         }
507         if (fsp->fh->fd == -1) {
508                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
509                 return False;
510         }
511         fsp->num_smb_operations++;
512         return True;
513 }
514
515 /****************************************************************************
516  Check if we have a correct fsp pointing to a quota fake file. Replacement for
517  the CHECK_NTQUOTA_HANDLE_OK macro.
518 ****************************************************************************/
519
520 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
521                               files_struct *fsp)
522 {
523         if (!check_fsp_open(conn, req, fsp)) {
524                 return false;
525         }
526
527         if (fsp->fsp_flags.is_directory) {
528                 return false;
529         }
530
531         if (fsp->fake_file_handle == NULL) {
532                 return false;
533         }
534
535         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536                 return false;
537         }
538
539         if (fsp->fake_file_handle->private_data == NULL) {
540                 return false;
541         }
542
543         return true;
544 }
545
546 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
547                                      const char *name, int name_type)
548 {
549         char *trim_name;
550         char *trim_name_type;
551         const char *retarget_parm;
552         char *retarget;
553         char *p;
554         int retarget_type = 0x20;
555         int retarget_port = NBT_SMB_PORT;
556         struct sockaddr_storage retarget_addr;
557         struct sockaddr_in *in_addr;
558         bool ret = false;
559         uint8_t outbuf[10];
560
561         if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562                 return false;
563         }
564
565         trim_name = talloc_strdup(talloc_tos(), name);
566         if (trim_name == NULL) {
567                 goto fail;
568         }
569         trim_char(trim_name, ' ', ' ');
570
571         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
572                                          name_type);
573         if (trim_name_type == NULL) {
574                 goto fail;
575         }
576
577         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578                                              trim_name_type, NULL);
579         if (retarget_parm == NULL) {
580                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
581                                                      trim_name, NULL);
582         }
583         if (retarget_parm == NULL) {
584                 goto fail;
585         }
586
587         retarget = talloc_strdup(trim_name, retarget_parm);
588         if (retarget == NULL) {
589                 goto fail;
590         }
591
592         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
593
594         p = strchr(retarget, ':');
595         if (p != NULL) {
596                 *p++ = '\0';
597                 retarget_port = atoi(p);
598         }
599
600         p = strchr_m(retarget, '#');
601         if (p != NULL) {
602                 *p++ = '\0';
603                 if (sscanf(p, "%x", &retarget_type) != 1) {
604                         goto fail;
605                 }
606         }
607
608         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
609         if (!ret) {
610                 DEBUG(10, ("could not resolve %s\n", retarget));
611                 goto fail;
612         }
613
614         if (retarget_addr.ss_family != AF_INET) {
615                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616                 goto fail;
617         }
618
619         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
620
621         _smb_setlen(outbuf, 6);
622         SCVAL(outbuf, 0, 0x84);
623         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
624         *(uint16_t *)(outbuf+8) = htons(retarget_port);
625
626         if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
627                           NULL)) {
628                 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
629                                     "failed.");
630         }
631
632         ret = true;
633  fail:
634         TALLOC_FREE(trim_name);
635         return ret;
636 }
637
638 static void reply_called_name_not_present(char *outbuf)
639 {
640         smb_setlen(outbuf, 1);
641         SCVAL(outbuf, 0, 0x83);
642         SCVAL(outbuf, 4, 0x82);
643 }
644
645 /****************************************************************************
646  Reply to a (netbios-level) special message. 
647 ****************************************************************************/
648
649 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
650 {
651         struct smbd_server_connection *sconn = xconn->client->sconn;
652         int msg_type = CVAL(inbuf,0);
653         int msg_flags = CVAL(inbuf,1);
654         /*
655          * We only really use 4 bytes of the outbuf, but for the smb_setlen
656          * calculation & friends (srv_send_smb uses that) we need the full smb
657          * header.
658          */
659         char outbuf[smb_size];
660
661         memset(outbuf, '\0', sizeof(outbuf));
662
663         smb_setlen(outbuf,0);
664
665         switch (msg_type) {
666         case NBSSrequest: /* session request */
667         {
668                 /* inbuf_size is guarenteed to be at least 4. */
669                 fstring name1,name2;
670                 int name_type1, name_type2;
671                 int name_len1, name_len2;
672
673                 *name1 = *name2 = 0;
674
675                 if (xconn->transport.nbt.got_session) {
676                         exit_server_cleanly("multiple session request not permitted");
677                 }
678
679                 SCVAL(outbuf,0,NBSSpositive);
680                 SCVAL(outbuf,3,0);
681
682                 /* inbuf_size is guaranteed to be at least 4. */
683                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
684                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
685                         DEBUG(0,("Invalid name length in session request\n"));
686                         reply_called_name_not_present(outbuf);
687                         break;
688                 }
689                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
690                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
691                         DEBUG(0,("Invalid name length in session request\n"));
692                         reply_called_name_not_present(outbuf);
693                         break;
694                 }
695
696                 name_type1 = name_extract((unsigned char *)inbuf,
697                                 inbuf_size,(unsigned int)4,name1);
698                 name_type2 = name_extract((unsigned char *)inbuf,
699                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
700
701                 if (name_type1 == -1 || name_type2 == -1) {
702                         DEBUG(0,("Invalid name type in session request\n"));
703                         reply_called_name_not_present(outbuf);
704                         break;
705                 }
706
707                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
708                          name1, name_type1, name2, name_type2));
709
710                 if (netbios_session_retarget(xconn, name1, name_type1)) {
711                         exit_server_cleanly("retargeted client");
712                 }
713
714                 /*
715                  * Windows NT/2k uses "*SMBSERVER" and XP uses
716                  * "*SMBSERV" arrggg!!!
717                  */
718                 if (strequal(name1, "*SMBSERVER     ")
719                     || strequal(name1, "*SMBSERV       "))  {
720                         char *raddr;
721
722                         raddr = tsocket_address_inet_addr_string(sconn->remote_address,
723                                                                  talloc_tos());
724                         if (raddr == NULL) {
725                                 exit_server_cleanly("could not allocate raddr");
726                         }
727
728                         fstrcpy(name1, raddr);
729                 }
730
731                 set_local_machine_name(name1, True);
732                 set_remote_machine_name(name2, True);
733
734                 if (is_ipaddress(sconn->remote_hostname)) {
735                         char *p = discard_const_p(char, sconn->remote_hostname);
736
737                         talloc_free(p);
738
739                         sconn->remote_hostname = talloc_strdup(sconn,
740                                                 get_remote_machine_name());
741                         if (sconn->remote_hostname == NULL) {
742                                 exit_server_cleanly("could not copy remote name");
743                         }
744                         xconn->remote_hostname = sconn->remote_hostname;
745                 }
746
747                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
748                          get_local_machine_name(), get_remote_machine_name(),
749                          name_type2));
750
751                 if (name_type2 == 'R') {
752                         /* We are being asked for a pathworks session --- 
753                            no thanks! */
754                         reply_called_name_not_present(outbuf);
755                         break;
756                 }
757
758                 reload_services(sconn, conn_snum_used, true);
759                 reopen_logs();
760
761                 xconn->transport.nbt.got_session = true;
762                 break;
763         }
764
765         case 0x89: /* session keepalive request 
766                       (some old clients produce this?) */
767                 SCVAL(outbuf,0,NBSSkeepalive);
768                 SCVAL(outbuf,3,0);
769                 break;
770
771         case NBSSpositive: /* positive session response */
772         case NBSSnegative: /* negative session response */
773         case NBSSretarget: /* retarget session response */
774                 DEBUG(0,("Unexpected session response\n"));
775                 break;
776
777         case NBSSkeepalive: /* session keepalive */
778         default:
779                 return;
780         }
781
782         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
783                     msg_type, msg_flags));
784
785         if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
786                 exit_server_cleanly("reply_special: srv_send_smb failed.");
787         }
788
789         if (CVAL(outbuf, 0) != 0x82) {
790                 exit_server_cleanly("invalid netbios session");
791         }
792         return;
793 }
794
795 /****************************************************************************
796  Reply to a tcon.
797  conn POINTER CAN BE NULL HERE !
798 ****************************************************************************/
799
800 void reply_tcon(struct smb_request *req)
801 {
802         connection_struct *conn = req->conn;
803         const char *service;
804         char *service_buf = NULL;
805         char *password = NULL;
806         char *dev = NULL;
807         int pwlen=0;
808         NTSTATUS nt_status;
809         const uint8_t *p;
810         const char *p2;
811         TALLOC_CTX *ctx = talloc_tos();
812         struct smbXsrv_connection *xconn = req->xconn;
813         NTTIME now = timeval_to_nttime(&req->request_time);
814
815         START_PROFILE(SMBtcon);
816
817         if (req->buflen < 4) {
818                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
819                 END_PROFILE(SMBtcon);
820                 return;
821         }
822
823         p = req->buf + 1;
824         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
825         p += 1;
826         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
827         p += pwlen+1;
828         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
829         p += 1;
830
831         if (service_buf == NULL || password == NULL || dev == NULL) {
832                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833                 END_PROFILE(SMBtcon);
834                 return;
835         }
836         p2 = strrchr_m(service_buf,'\\');
837         if (p2) {
838                 service = p2+1;
839         } else {
840                 service = service_buf;
841         }
842
843         conn = make_connection(req, now, service, dev,
844                                req->vuid,&nt_status);
845         req->conn = conn;
846
847         if (!conn) {
848                 reply_nterror(req, nt_status);
849                 END_PROFILE(SMBtcon);
850                 return;
851         }
852
853         reply_outbuf(req, 2, 0);
854         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
855         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
856         SSVAL(req->outbuf,smb_tid,conn->cnum);
857
858         DEBUG(3,("tcon service=%s cnum=%d\n",
859                  service, conn->cnum));
860
861         END_PROFILE(SMBtcon);
862         return;
863 }
864
865 /****************************************************************************
866  Reply to a tcon and X.
867  conn POINTER CAN BE NULL HERE !
868 ****************************************************************************/
869
870 void reply_tcon_and_X(struct smb_request *req)
871 {
872         const struct loadparm_substitution *lp_sub =
873                 loadparm_s3_global_substitution();
874         connection_struct *conn = req->conn;
875         const char *service = NULL;
876         TALLOC_CTX *ctx = talloc_tos();
877         /* what the client thinks the device is */
878         char *client_devicetype = NULL;
879         /* what the server tells the client the share represents */
880         const char *server_devicetype;
881         NTSTATUS nt_status;
882         int passlen;
883         char *path = NULL;
884         const uint8_t *p;
885         const char *q;
886         uint16_t tcon_flags;
887         struct smbXsrv_session *session = NULL;
888         NTTIME now = timeval_to_nttime(&req->request_time);
889         bool session_key_updated = false;
890         uint16_t optional_support = 0;
891         struct smbXsrv_connection *xconn = req->xconn;
892
893         START_PROFILE(SMBtconX);
894
895         if (req->wct < 4) {
896                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897                 END_PROFILE(SMBtconX);
898                 return;
899         }
900
901         passlen = SVAL(req->vwv+3, 0);
902         tcon_flags = SVAL(req->vwv+2, 0);
903
904         /* we might have to close an old one */
905         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
906                 struct smbXsrv_tcon *tcon;
907                 NTSTATUS status;
908
909                 tcon = conn->tcon;
910                 req->conn = NULL;
911                 conn = NULL;
912
913                 /*
914                  * TODO: cancel all outstanding requests on the tcon
915                  */
916                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
917                 if (!NT_STATUS_IS_OK(status)) {
918                         DEBUG(0, ("reply_tcon_and_X: "
919                                   "smbXsrv_tcon_disconnect() failed: %s\n",
920                                   nt_errstr(status)));
921                         /*
922                          * If we hit this case, there is something completely
923                          * wrong, so we better disconnect the transport connection.
924                          */
925                         END_PROFILE(SMBtconX);
926                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
927                         return;
928                 }
929
930                 TALLOC_FREE(tcon);
931                 /*
932                  * This tree id is gone. Make sure we can't re-use it
933                  * by accident.
934                  */
935                 req->tid = 0;
936         }
937
938         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
939                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
940                 END_PROFILE(SMBtconX);
941                 return;
942         }
943
944         if (xconn->smb1.negprot.encrypted_passwords) {
945                 p = req->buf + passlen;
946         } else {
947                 p = req->buf + passlen + 1;
948         }
949
950         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
951
952         if (path == NULL) {
953                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
954                 END_PROFILE(SMBtconX);
955                 return;
956         }
957
958         /*
959          * the service name can be either: \\server\share
960          * or share directly like on the DELL PowerVault 705
961          */
962         if (*path=='\\') {
963                 q = strchr_m(path+2,'\\');
964                 if (!q) {
965                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
966                         END_PROFILE(SMBtconX);
967                         return;
968                 }
969                 service = q+1;
970         } else {
971                 service = path;
972         }
973
974         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
975                                 &client_devicetype, p,
976                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
977
978         if (client_devicetype == NULL) {
979                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980                 END_PROFILE(SMBtconX);
981                 return;
982         }
983
984         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
985
986         nt_status = smb1srv_session_lookup(xconn,
987                                            req->vuid, now, &session);
988         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
989                 reply_force_doserror(req, ERRSRV, ERRbaduid);
990                 END_PROFILE(SMBtconX);
991                 return;
992         }
993         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
994                 reply_nterror(req, nt_status);
995                 END_PROFILE(SMBtconX);
996                 return;
997         }
998         if (!NT_STATUS_IS_OK(nt_status)) {
999                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1000                 END_PROFILE(SMBtconX);
1001                 return;
1002         }
1003
1004         if (session->global->auth_session_info == NULL) {
1005                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1006                 END_PROFILE(SMBtconX);
1007                 return;
1008         }
1009
1010         /*
1011          * If there is no application key defined yet
1012          * we create one.
1013          *
1014          * This means we setup the application key on the
1015          * first tcon that happens via the given session.
1016          *
1017          * Once the application key is defined, it does not
1018          * change any more.
1019          */
1020         if (session->global->application_key.length == 0 &&
1021             smb2_signing_key_valid(session->global->signing_key))
1022         {
1023                 struct smbXsrv_session *x = session;
1024                 struct auth_session_info *session_info =
1025                         session->global->auth_session_info;
1026                 uint8_t session_key[16];
1027
1028                 ZERO_STRUCT(session_key);
1029                 memcpy(session_key, x->global->signing_key->blob.data,
1030                        MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1031
1032                 /*
1033                  * The application key is truncated/padded to 16 bytes
1034                  */
1035                 x->global->application_key = data_blob_talloc(x->global,
1036                                                              session_key,
1037                                                              sizeof(session_key));
1038                 ZERO_STRUCT(session_key);
1039                 if (x->global->application_key.data == NULL) {
1040                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1041                         END_PROFILE(SMBtconX);
1042                         return;
1043                 }
1044
1045                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1046                         NTSTATUS status;
1047
1048                         status = smb_key_derivation(x->global->application_key.data,
1049                                                     x->global->application_key.length,
1050                                                     x->global->application_key.data);
1051                         if (!NT_STATUS_IS_OK(status)) {
1052                                 DBG_ERR("smb_key_derivation failed: %s\n",
1053                                         nt_errstr(status));
1054                                 END_PROFILE(SMBtconX);
1055                                 return;
1056                         }
1057                         optional_support |= SMB_EXTENDED_SIGNATURES;
1058                 }
1059
1060                 /*
1061                  * Place the application key into the session_info
1062                  */
1063                 data_blob_clear_free(&session_info->session_key);
1064                 session_info->session_key = data_blob_dup_talloc(session_info,
1065                                                 x->global->application_key);
1066                 if (session_info->session_key.data == NULL) {
1067                         data_blob_clear_free(&x->global->application_key);
1068                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1069                         END_PROFILE(SMBtconX);
1070                         return;
1071                 }
1072                 session_key_updated = true;
1073         }
1074
1075         conn = make_connection(req, now, service, client_devicetype,
1076                                req->vuid, &nt_status);
1077         req->conn =conn;
1078
1079         if (!conn) {
1080                 if (session_key_updated) {
1081                         struct smbXsrv_session *x = session;
1082                         struct auth_session_info *session_info =
1083                                 session->global->auth_session_info;
1084                         data_blob_clear_free(&x->global->application_key);
1085                         data_blob_clear_free(&session_info->session_key);
1086                 }
1087                 reply_nterror(req, nt_status);
1088                 END_PROFILE(SMBtconX);
1089                 return;
1090         }
1091
1092         if ( IS_IPC(conn) )
1093                 server_devicetype = "IPC";
1094         else if ( IS_PRINT(conn) )
1095                 server_devicetype = "LPT1:";
1096         else
1097                 server_devicetype = "A:";
1098
1099         if (get_Protocol() < PROTOCOL_NT1) {
1100                 reply_outbuf(req, 2, 0);
1101                 if (message_push_string(&req->outbuf, server_devicetype,
1102                                         STR_TERMINATE|STR_ASCII) == -1) {
1103                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1104                         END_PROFILE(SMBtconX);
1105                         return;
1106                 }
1107         } else {
1108                 /* NT sets the fstype of IPC$ to the null string */
1109                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1110
1111                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1112                         /* Return permissions. */
1113                         uint32_t perm1 = 0;
1114                         uint32_t perm2 = 0;
1115
1116                         reply_outbuf(req, 7, 0);
1117
1118                         if (IS_IPC(conn)) {
1119                                 perm1 = FILE_ALL_ACCESS;
1120                                 perm2 = FILE_ALL_ACCESS;
1121                         } else {
1122                                 perm1 = conn->share_access;
1123                         }
1124
1125                         SIVAL(req->outbuf, smb_vwv3, perm1);
1126                         SIVAL(req->outbuf, smb_vwv5, perm2);
1127                 } else {
1128                         reply_outbuf(req, 3, 0);
1129                 }
1130
1131                 if ((message_push_string(&req->outbuf, server_devicetype,
1132                                          STR_TERMINATE|STR_ASCII) == -1)
1133                     || (message_push_string(&req->outbuf, fstype,
1134                                             STR_TERMINATE) == -1)) {
1135                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1136                         END_PROFILE(SMBtconX);
1137                         return;
1138                 }
1139
1140                 /* what does setting this bit do? It is set by NT4 and
1141                    may affect the ability to autorun mounted cdroms */
1142                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1143                 optional_support |=
1144                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1145
1146                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1147                         DEBUG(2,("Serving %s as a Dfs root\n",
1148                                  lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1149                         optional_support |= SMB_SHARE_IN_DFS;
1150                 }
1151
1152                 SSVAL(req->outbuf, smb_vwv2, optional_support);
1153         }
1154
1155         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1156         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1157
1158         DEBUG(3,("tconX service=%s \n",
1159                  service));
1160
1161         /* set the incoming and outgoing tid to the just created one */
1162         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1163         SSVAL(req->outbuf,smb_tid,conn->cnum);
1164
1165         END_PROFILE(SMBtconX);
1166
1167         req->tid = conn->cnum;
1168 }
1169
1170 /****************************************************************************
1171  Reply to an unknown type.
1172 ****************************************************************************/
1173
1174 void reply_unknown_new(struct smb_request *req, uint8_t type)
1175 {
1176         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1177                   smb_fn_name(type), type, type));
1178         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1179         return;
1180 }
1181
1182 /****************************************************************************
1183  Reply to an ioctl.
1184  conn POINTER CAN BE NULL HERE !
1185 ****************************************************************************/
1186
1187 void reply_ioctl(struct smb_request *req)
1188 {
1189         const struct loadparm_substitution *lp_sub =
1190                 loadparm_s3_global_substitution();
1191         connection_struct *conn = req->conn;
1192         uint16_t device;
1193         uint16_t function;
1194         uint32_t ioctl_code;
1195         int replysize;
1196         char *p;
1197
1198         START_PROFILE(SMBioctl);
1199
1200         if (req->wct < 3) {
1201                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202                 END_PROFILE(SMBioctl);
1203                 return;
1204         }
1205
1206         device     = SVAL(req->vwv+1, 0);
1207         function   = SVAL(req->vwv+2, 0);
1208         ioctl_code = (device << 16) + function;
1209
1210         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1211
1212         switch (ioctl_code) {
1213             case IOCTL_QUERY_JOB_INFO:
1214                     replysize = 32;
1215                     break;
1216             default:
1217                     reply_force_doserror(req, ERRSRV, ERRnosupport);
1218                     END_PROFILE(SMBioctl);
1219                     return;
1220         }
1221
1222         reply_outbuf(req, 8, replysize+1);
1223         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1224         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1225         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
1226         p = smb_buf(req->outbuf);
1227         memset(p, '\0', replysize+1); /* valgrind-safe. */
1228         p += 1;          /* Allow for alignment */
1229
1230         switch (ioctl_code) {
1231                 case IOCTL_QUERY_JOB_INFO:                  
1232                 {
1233                         NTSTATUS status;
1234                         size_t len = 0;
1235                         files_struct *fsp = file_fsp(
1236                                 req, SVAL(req->vwv+0, 0));
1237                         if (!fsp) {
1238                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1239                                 END_PROFILE(SMBioctl);
1240                                 return;
1241                         }
1242                         /* Job number */
1243                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1244
1245                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1246                                     lp_netbios_name(), 15,
1247                                     STR_TERMINATE|STR_ASCII, &len);
1248                         if (!NT_STATUS_IS_OK(status)) {
1249                                 reply_nterror(req, status);
1250                                 END_PROFILE(SMBioctl);
1251                                 return;
1252                         }
1253                         if (conn) {
1254                                 status = srvstr_push((char *)req->outbuf, req->flags2,
1255                                             p+18,
1256                                             lp_servicename(talloc_tos(),
1257                                                            lp_sub,
1258                                                            SNUM(conn)),
1259                                             13, STR_TERMINATE|STR_ASCII, &len);
1260                                 if (!NT_STATUS_IS_OK(status)) {
1261                                         reply_nterror(req, status);
1262                                         END_PROFILE(SMBioctl);
1263                                         return;
1264                                 }
1265                         } else {
1266                                 memset(p+18, 0, 13);
1267                         }
1268                         break;
1269                 }
1270         }
1271
1272         END_PROFILE(SMBioctl);
1273         return;
1274 }
1275
1276 /****************************************************************************
1277  Strange checkpath NTSTATUS mapping.
1278 ****************************************************************************/
1279
1280 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1281 {
1282         /* Strange DOS error code semantics only for checkpath... */
1283         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1284                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1285                         /* We need to map to ERRbadpath */
1286                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1287                 }
1288         }
1289         return status;
1290 }
1291
1292 /****************************************************************************
1293  Reply to a checkpath.
1294 ****************************************************************************/
1295
1296 void reply_checkpath(struct smb_request *req)
1297 {
1298         connection_struct *conn = req->conn;
1299         struct smb_filename *smb_fname = NULL;
1300         char *name = NULL;
1301         NTSTATUS status;
1302         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1303         TALLOC_CTX *ctx = talloc_tos();
1304
1305         START_PROFILE(SMBcheckpath);
1306
1307         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1308                             STR_TERMINATE, &status);
1309
1310         if (!NT_STATUS_IS_OK(status)) {
1311                 status = map_checkpath_error(req->flags2, status);
1312                 reply_nterror(req, status);
1313                 END_PROFILE(SMBcheckpath);
1314                 return;
1315         }
1316
1317         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1318
1319         status = filename_convert(ctx,
1320                                 conn,
1321                                 name,
1322                                 ucf_flags,
1323                                 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->fsp_flags.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, smb_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->fsp_flags.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->fsp_flags.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->fsp_flags.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->fsp_flags.is_directory ?
6036                   "directory" : "file",
6037                   fsp->fh->fd, fsp_fnum_dbg(fsp),
6038                   conn->num_files_open);
6039
6040         if (!fsp->fsp_flags.is_directory) {
6041                 time_t t;
6042
6043                 /*
6044                  * Take care of any time sent in the close.
6045                  */
6046
6047                 t = srv_make_unix_date3(smb1req->vwv+1);
6048                 set_close_write_time(fsp, time_t_to_full_timespec(t));
6049         }
6050
6051         if (fsp->num_aio_requests != 0) {
6052                 struct tevent_req *req;
6053
6054                 req = reply_close_send(smb1req, fsp);
6055                 if (req == NULL) {
6056                         status = NT_STATUS_NO_MEMORY;
6057                         goto done;
6058                 }
6059                 /* We're async. This will complete later. */
6060                 tevent_req_set_callback(req, reply_close_done, smb1req);
6061                 END_PROFILE(SMBclose);
6062                 return;
6063         }
6064
6065         /*
6066          * close_file() returns the unix errno if an error was detected on
6067          * close - normally this is due to a disk full error. If not then it
6068          * was probably an I/O error.
6069          */
6070
6071         status = close_file(smb1req, fsp, NORMAL_CLOSE);
6072 done:
6073         if (!NT_STATUS_IS_OK(status)) {
6074                 reply_nterror(smb1req, status);
6075                 END_PROFILE(SMBclose);
6076                 return;
6077         }
6078
6079         reply_outbuf(smb1req, 0, 0);
6080         END_PROFILE(SMBclose);
6081         return;
6082 }
6083
6084 struct reply_close_state {
6085         files_struct *fsp;
6086         struct tevent_queue *wait_queue;
6087 };
6088
6089 static void reply_close_wait_done(struct tevent_req *subreq);
6090
6091 /****************************************************************************
6092  Async SMB1 close.
6093  Note, on failure here we deallocate and return NULL to allow the caller to
6094  SMB1 return an error of ERRnomem immediately.
6095 ****************************************************************************/
6096
6097 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6098                                 files_struct *fsp)
6099 {
6100         struct tevent_req *req;
6101         struct reply_close_state *state;
6102         struct tevent_req *subreq;
6103         struct smbd_server_connection *sconn = smb1req->sconn;
6104
6105         req = tevent_req_create(smb1req, &state,
6106                         struct reply_close_state);
6107         if (req == NULL) {
6108                 return NULL;
6109         }
6110         state->wait_queue = tevent_queue_create(state,
6111                                 "reply_close_wait_queue");
6112         if (tevent_req_nomem(state->wait_queue, req)) {
6113                 TALLOC_FREE(req);
6114                 return NULL;
6115         }
6116
6117         /*
6118          * Flag the file as close in progress.
6119          * This will prevent any more IO being
6120          * done on it.
6121          */
6122         fsp->fsp_flags.closing = true;
6123
6124         /*
6125          * Now wait until all aio requests on this fsp are
6126          * finished.
6127          *
6128          * We don't set a callback, as we just want to block the
6129          * wait queue and the talloc_free() of fsp->aio_request
6130          * will remove the item from the wait queue.
6131          */
6132         subreq = tevent_queue_wait_send(fsp->aio_requests,
6133                                         sconn->ev_ctx,
6134                                         state->wait_queue);
6135         if (tevent_req_nomem(subreq, req)) {
6136                 TALLOC_FREE(req);
6137                 return NULL;
6138         }
6139
6140         /*
6141          * Now we add our own waiter to the end of the queue,
6142          * this way we get notified when all pending requests are finished
6143          * and reply to the outstanding SMB1 request.
6144          */
6145         subreq = tevent_queue_wait_send(state,
6146                                 sconn->ev_ctx,
6147                                 state->wait_queue);
6148         if (tevent_req_nomem(subreq, req)) {
6149                 TALLOC_FREE(req);
6150                 return NULL;
6151         }
6152
6153         /*
6154          * We're really going async - move the SMB1 request from
6155          * a talloc stackframe above us to the conn talloc-context.
6156          * We need this to stick around until the wait_done
6157          * callback is invoked.
6158          */
6159         smb1req = talloc_move(sconn, &smb1req);
6160
6161         tevent_req_set_callback(subreq, reply_close_wait_done, req);
6162
6163         return req;
6164 }
6165
6166 static void reply_close_wait_done(struct tevent_req *subreq)
6167 {
6168         struct tevent_req *req = tevent_req_callback_data(
6169                 subreq, struct tevent_req);
6170
6171         tevent_queue_wait_recv(subreq);
6172         TALLOC_FREE(subreq);
6173         tevent_req_done(req);
6174 }
6175
6176 static NTSTATUS reply_close_recv(struct tevent_req *req)
6177 {
6178         return tevent_req_simple_recv_ntstatus(req);
6179 }
6180
6181 static void reply_close_done(struct tevent_req *req)
6182 {
6183         struct smb_request *smb1req = tevent_req_callback_data(
6184                         req, struct smb_request);
6185         struct reply_close_state *state = tevent_req_data(req,
6186                                                 struct reply_close_state);
6187         NTSTATUS status;
6188
6189         status = reply_close_recv(req);
6190         TALLOC_FREE(req);
6191         if (!NT_STATUS_IS_OK(status)) {
6192                 TALLOC_FREE(smb1req);
6193                 exit_server(__location__ ": reply_close_recv failed");
6194                 return;
6195         }
6196
6197         status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6198         if (NT_STATUS_IS_OK(status)) {
6199                 reply_outbuf(smb1req, 0, 0);
6200         } else {
6201                 reply_nterror(smb1req, status);
6202         }
6203         /*
6204          * The following call is needed to push the
6205          * reply data back out the socket after async
6206          * return. Plus it frees smb1req.
6207          */
6208         smb_request_done(smb1req);
6209 }
6210
6211 /****************************************************************************
6212  Reply to a writeclose (Core+ protocol).
6213 ****************************************************************************/
6214
6215 void reply_writeclose(struct smb_request *req)
6216 {
6217         connection_struct *conn = req->conn;
6218         size_t numtowrite;
6219         size_t remaining;
6220         ssize_t nwritten = -1;
6221         NTSTATUS close_status = NT_STATUS_OK;
6222         off_t startpos;
6223         const char *data;
6224         struct timespec mtime;
6225         files_struct *fsp;
6226         struct lock_struct lock;
6227
6228         START_PROFILE(SMBwriteclose);
6229
6230         if (req->wct < 6) {
6231                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6232                 END_PROFILE(SMBwriteclose);
6233                 return;
6234         }
6235
6236         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6237
6238         if (!check_fsp(conn, req, fsp)) {
6239                 END_PROFILE(SMBwriteclose);
6240                 return;
6241         }
6242         if (!CHECK_WRITE(fsp)) {
6243                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6244                 END_PROFILE(SMBwriteclose);
6245                 return;
6246         }
6247
6248         numtowrite = SVAL(req->vwv+1, 0);
6249         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6250         mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6251         data = (const char *)req->buf + 1;
6252
6253         /*
6254          * Ensure client isn't asking us to write more than
6255          * they sent. CVE-2017-12163.
6256          */
6257         remaining = smbreq_bufrem(req, data);
6258         if (numtowrite > remaining) {
6259                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6260                 END_PROFILE(SMBwriteclose);
6261                 return;
6262         }
6263
6264         if (fsp->print_file == NULL) {
6265                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6266                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6267                     &lock);
6268
6269                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6270                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6271                         END_PROFILE(SMBwriteclose);
6272                         return;
6273                 }
6274         }
6275
6276         nwritten = write_file(req,fsp,data,startpos,numtowrite);
6277
6278         set_close_write_time(fsp, mtime);
6279
6280         /*
6281          * More insanity. W2K only closes the file if writelen > 0.
6282          * JRA.
6283          */
6284
6285         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6286                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6287                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6288
6289         if (numtowrite) {
6290                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6291                          "file %s\n", fsp_str_dbg(fsp)));
6292                 close_status = close_file(req, fsp, NORMAL_CLOSE);
6293                 fsp = NULL;
6294         }
6295
6296         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6297                 reply_nterror(req, NT_STATUS_DISK_FULL);
6298                 goto out;
6299         }
6300
6301         if(!NT_STATUS_IS_OK(close_status)) {
6302                 reply_nterror(req, close_status);
6303                 goto out;
6304         }
6305
6306         reply_outbuf(req, 1, 0);
6307
6308         SSVAL(req->outbuf,smb_vwv0,nwritten);
6309
6310 out:
6311
6312         END_PROFILE(SMBwriteclose);
6313         return;
6314 }
6315
6316 #undef DBGC_CLASS
6317 #define DBGC_CLASS DBGC_LOCKING
6318
6319 /****************************************************************************
6320  Reply to a lock.
6321 ****************************************************************************/
6322
6323 static void reply_lock_done(struct tevent_req *subreq);
6324
6325 void reply_lock(struct smb_request *req)
6326 {
6327         struct tevent_req *subreq = NULL;
6328         connection_struct *conn = req->conn;
6329         files_struct *fsp;
6330         struct smbd_lock_element *lck = NULL;
6331
6332         START_PROFILE(SMBlock);
6333
6334         if (req->wct < 5) {
6335                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6336                 END_PROFILE(SMBlock);
6337                 return;
6338         }
6339
6340         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6341
6342         if (!check_fsp(conn, req, fsp)) {
6343                 END_PROFILE(SMBlock);
6344                 return;
6345         }
6346
6347         lck = talloc(req, struct smbd_lock_element);
6348         if (lck == NULL) {
6349                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6350                 END_PROFILE(SMBlock);
6351                 return;
6352         }
6353
6354         *lck = (struct smbd_lock_element) {
6355                 .req_guid = smbd_request_guid(req, 0),
6356                 .smblctx = req->smbpid,
6357                 .brltype = WRITE_LOCK,
6358                 .count = IVAL(req->vwv+1, 0),
6359                 .offset = IVAL(req->vwv+3, 0),
6360         };
6361
6362         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6363                    fsp->fh->fd,
6364                    fsp_fnum_dbg(fsp),
6365                    lck->offset,
6366                    lck->count);
6367
6368         subreq = smbd_smb1_do_locks_send(
6369                 fsp,
6370                 req->sconn->ev_ctx,
6371                 &req,
6372                 fsp,
6373                 0,
6374                 false,          /* large_offset */
6375                 WINDOWS_LOCK,
6376                 1,
6377                 lck);
6378         if (subreq == NULL) {
6379                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6380                 END_PROFILE(SMBlock);
6381                 return;
6382         }
6383         tevent_req_set_callback(subreq, reply_lock_done, NULL);
6384         END_PROFILE(SMBlock);
6385 }
6386
6387 static void reply_lock_done(struct tevent_req *subreq)
6388 {
6389         struct smb_request *req = NULL;
6390         NTSTATUS status;
6391         bool ok;
6392
6393         START_PROFILE(SMBlock);
6394
6395         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6396         SMB_ASSERT(ok);
6397
6398         status = smbd_smb1_do_locks_recv(subreq);
6399         TALLOC_FREE(subreq);
6400
6401         if (NT_STATUS_IS_OK(status)) {
6402                 reply_outbuf(req, 0, 0);
6403         } else {
6404                 reply_nterror(req, status);
6405         }
6406
6407         ok = srv_send_smb(req->xconn,
6408                           (char *)req->outbuf,
6409                           true,
6410                           req->seqnum+1,
6411                           IS_CONN_ENCRYPTED(req->conn),
6412                           NULL);
6413         if (!ok) {
6414                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6415         }
6416         TALLOC_FREE(req);
6417         END_PROFILE(SMBlock);
6418 }
6419
6420 /****************************************************************************
6421  Reply to a unlock.
6422 ****************************************************************************/
6423
6424 void reply_unlock(struct smb_request *req)
6425 {
6426         connection_struct *conn = req->conn;
6427         NTSTATUS status;
6428         files_struct *fsp;
6429         struct smbd_lock_element lck;
6430
6431         START_PROFILE(SMBunlock);
6432
6433         if (req->wct < 5) {
6434                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6435                 END_PROFILE(SMBunlock);
6436                 return;
6437         }
6438
6439         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6440
6441         if (!check_fsp(conn, req, fsp)) {
6442                 END_PROFILE(SMBunlock);
6443                 return;
6444         }
6445
6446         lck = (struct smbd_lock_element) {
6447                 .req_guid = smbd_request_guid(req, 0),
6448                 .smblctx = req->smbpid,
6449                 .brltype = UNLOCK_LOCK,
6450                 .offset = IVAL(req->vwv+3, 0),
6451                 .count = IVAL(req->vwv+1, 0),
6452         };
6453
6454         status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6455
6456         if (!NT_STATUS_IS_OK(status)) {
6457                 reply_nterror(req, status);
6458                 END_PROFILE(SMBunlock);
6459                 return;
6460         }
6461
6462         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6463                    fsp->fh->fd,
6464                    fsp_fnum_dbg(fsp),
6465                    lck.offset,
6466                    lck.count);
6467
6468         reply_outbuf(req, 0, 0);
6469
6470         END_PROFILE(SMBunlock);
6471         return;
6472 }
6473
6474 #undef DBGC_CLASS
6475 #define DBGC_CLASS DBGC_ALL
6476
6477 /****************************************************************************
6478  Reply to a tdis.
6479  conn POINTER CAN BE NULL HERE !
6480 ****************************************************************************/
6481
6482 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6483 static void reply_tdis_done(struct tevent_req *req);
6484
6485 void reply_tdis(struct smb_request *smb1req)
6486 {
6487         connection_struct *conn = smb1req->conn;
6488         struct tevent_req *req;
6489
6490         /*
6491          * Don't setup the profile charge here, take
6492          * it in reply_tdis_done(). Not strictly correct
6493          * but better than the other SMB1 async
6494          * code that double-charges at the moment.
6495          */
6496
6497         if (conn == NULL) {
6498                 /* Not going async, profile here. */
6499                 START_PROFILE(SMBtdis);
6500                 DBG_INFO("Invalid connection in tdis\n");
6501                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6502                 END_PROFILE(SMBtdis);
6503                 return;
6504         }
6505
6506         req = reply_tdis_send(smb1req);
6507         if (req == NULL) {
6508                 /* Not going async, profile here. */
6509                 START_PROFILE(SMBtdis);
6510                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6511                 END_PROFILE(SMBtdis);
6512                 return;
6513         }
6514         /* We're async. This will complete later. */
6515         tevent_req_set_callback(req, reply_tdis_done, smb1req);
6516         return;
6517 }
6518
6519 struct reply_tdis_state {
6520         struct tevent_queue *wait_queue;
6521 };
6522
6523 static void reply_tdis_wait_done(struct tevent_req *subreq);
6524
6525 /****************************************************************************
6526  Async SMB1 tdis.
6527  Note, on failure here we deallocate and return NULL to allow the caller to
6528  SMB1 return an error of ERRnomem immediately.
6529 ****************************************************************************/
6530
6531 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6532 {
6533         struct tevent_req *req;
6534         struct reply_tdis_state *state;
6535         struct tevent_req *subreq;
6536         connection_struct *conn = smb1req->conn;
6537         files_struct *fsp;
6538
6539         req = tevent_req_create(smb1req, &state,
6540                         struct reply_tdis_state);
6541         if (req == NULL) {
6542                 return NULL;
6543         }
6544         state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6545         if (tevent_req_nomem(state->wait_queue, req)) {
6546                 TALLOC_FREE(req);
6547                 return NULL;
6548         }
6549
6550         /*
6551          * Make sure that no new request will be able to use this tcon.
6552          * This ensures that once all outstanding fsp->aio_requests
6553          * on this tcon are done, we are safe to close it.
6554          */
6555         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6556
6557         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6558                 if (fsp->conn != conn) {
6559                         continue;
6560                 }
6561                 /*
6562                  * Flag the file as close in progress.
6563                  * This will prevent any more IO being
6564                  * done on it. Not strictly needed, but
6565                  * doesn't hurt to flag it as closing.
6566                  */
6567                 fsp->fsp_flags.closing = true;
6568
6569                 if (fsp->num_aio_requests > 0) {
6570                         /*
6571                          * Now wait until all aio requests on this fsp are
6572                          * finished.
6573                          *
6574                          * We don't set a callback, as we just want to block the
6575                          * wait queue and the talloc_free() of fsp->aio_request
6576                          * will remove the item from the wait queue.
6577                          */
6578                         subreq = tevent_queue_wait_send(fsp->aio_requests,
6579                                                 conn->sconn->ev_ctx,
6580                                                 state->wait_queue);
6581                         if (tevent_req_nomem(subreq, req)) {
6582                                 TALLOC_FREE(req);
6583                                 return NULL;
6584                         }
6585                 }
6586         }
6587
6588         /*
6589          * Now we add our own waiter to the end of the queue,
6590          * this way we get notified when all pending requests are finished
6591          * and reply to the outstanding SMB1 request.
6592          */
6593         subreq = tevent_queue_wait_send(state,
6594                                 conn->sconn->ev_ctx,
6595                                 state->wait_queue);
6596         if (tevent_req_nomem(subreq, req)) {
6597                 TALLOC_FREE(req);
6598                 return NULL;
6599         }
6600
6601         /*
6602          * We're really going async - move the SMB1 request from
6603          * a talloc stackframe above us to the sconn talloc-context.
6604          * We need this to stick around until the wait_done
6605          * callback is invoked.
6606          */
6607         smb1req = talloc_move(smb1req->sconn, &smb1req);
6608
6609         tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6610
6611         return req;
6612 }
6613
6614 static void reply_tdis_wait_done(struct tevent_req *subreq)
6615 {
6616         struct tevent_req *req = tevent_req_callback_data(
6617                 subreq, struct tevent_req);
6618
6619         tevent_queue_wait_recv(subreq);
6620         TALLOC_FREE(subreq);
6621         tevent_req_done(req);
6622 }
6623
6624 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6625 {
6626         return tevent_req_simple_recv_ntstatus(req);
6627 }
6628
6629 static void reply_tdis_done(struct tevent_req *req)
6630 {
6631         struct smb_request *smb1req = tevent_req_callback_data(
6632                 req, struct smb_request);
6633         NTSTATUS status;
6634         struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6635         bool ok;
6636
6637         /*
6638          * Take the profile charge here. Not strictly
6639          * correct but better than the other SMB1 async
6640          * code that double-charges at the moment.
6641          */
6642         START_PROFILE(SMBtdis);
6643
6644         status = reply_tdis_recv(req);
6645         TALLOC_FREE(req);
6646         if (!NT_STATUS_IS_OK(status)) {
6647                 TALLOC_FREE(smb1req);
6648                 END_PROFILE(SMBtdis);
6649                 exit_server(__location__ ": reply_tdis_recv failed");
6650                 return;
6651         }
6652
6653         /*
6654          * As we've been awoken, we may have changed
6655          * directory in the meantime.
6656          * reply_tdis() has the DO_CHDIR flag set.
6657          */
6658         ok = chdir_current_service(smb1req->conn);
6659         if (!ok) {
6660                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6661                 smb_request_done(smb1req);
6662                 END_PROFILE(SMBtdis);
6663         }
6664
6665         status = smbXsrv_tcon_disconnect(tcon,
6666                                          smb1req->vuid);
6667         if (!NT_STATUS_IS_OK(status)) {
6668                 TALLOC_FREE(smb1req);
6669                 END_PROFILE(SMBtdis);
6670                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6671                 return;
6672         }
6673
6674         /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6675         smb1req->conn = NULL;
6676
6677         TALLOC_FREE(tcon);
6678
6679         reply_outbuf(smb1req, 0, 0);
6680         /*
6681          * The following call is needed to push the
6682          * reply data back out the socket after async
6683          * return. Plus it frees smb1req.
6684          */
6685         smb_request_done(smb1req);
6686         END_PROFILE(SMBtdis);
6687 }
6688
6689 /****************************************************************************
6690  Reply to a echo.
6691  conn POINTER CAN BE NULL HERE !
6692 ****************************************************************************/
6693
6694 void reply_echo(struct smb_request *req)
6695 {
6696         connection_struct *conn = req->conn;
6697         struct smb_perfcount_data local_pcd;
6698         struct smb_perfcount_data *cur_pcd;
6699         int smb_reverb;
6700         int seq_num;
6701
6702         START_PROFILE(SMBecho);
6703
6704         smb_init_perfcount_data(&local_pcd);
6705
6706         if (req->wct < 1) {
6707                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6708                 END_PROFILE(SMBecho);
6709                 return;
6710         }
6711
6712         smb_reverb = SVAL(req->vwv+0, 0);
6713
6714         reply_outbuf(req, 1, req->buflen);
6715
6716         /* copy any incoming data back out */
6717         if (req->buflen > 0) {
6718                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6719         }
6720
6721         if (smb_reverb > 100) {
6722                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6723                 smb_reverb = 100;
6724         }
6725
6726         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6727
6728                 /* this makes sure we catch the request pcd */
6729                 if (seq_num == smb_reverb) {
6730                         cur_pcd = &req->pcd;
6731                 } else {
6732                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6733                         cur_pcd = &local_pcd;
6734                 }
6735
6736                 SSVAL(req->outbuf,smb_vwv0,seq_num);
6737
6738                 show_msg((char *)req->outbuf);
6739                 if (!srv_send_smb(req->xconn,
6740                                 (char *)req->outbuf,
6741                                 true, req->seqnum+1,
6742                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6743                                 cur_pcd))
6744                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
6745         }
6746
6747         DEBUG(3,("echo %d times\n", smb_reverb));
6748
6749         TALLOC_FREE(req->outbuf);
6750
6751         END_PROFILE(SMBecho);
6752         return;
6753 }
6754
6755 /****************************************************************************
6756  Reply to a printopen.
6757 ****************************************************************************/
6758
6759 void reply_printopen(struct smb_request *req)
6760 {
6761         connection_struct *conn = req->conn;
6762         files_struct *fsp;
6763         NTSTATUS status;
6764
6765         START_PROFILE(SMBsplopen);
6766
6767         if (req->wct < 2) {
6768                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6769                 END_PROFILE(SMBsplopen);
6770                 return;
6771         }
6772
6773         if (!CAN_PRINT(conn)) {
6774                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6775                 END_PROFILE(SMBsplopen);
6776                 return;
6777         }
6778
6779         status = file_new(req, conn, &fsp);
6780         if(!NT_STATUS_IS_OK(status)) {
6781                 reply_nterror(req, status);
6782                 END_PROFILE(SMBsplopen);
6783                 return;
6784         }
6785
6786         /* Open for exclusive use, write only. */
6787         status = print_spool_open(fsp, NULL, req->vuid);
6788
6789         if (!NT_STATUS_IS_OK(status)) {
6790                 file_free(req, fsp);
6791                 reply_nterror(req, status);
6792                 END_PROFILE(SMBsplopen);
6793                 return;
6794         }
6795
6796         reply_outbuf(req, 1, 0);
6797         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6798
6799         DEBUG(3,("openprint fd=%d %s\n",
6800                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6801
6802         END_PROFILE(SMBsplopen);
6803         return;
6804 }
6805
6806 /****************************************************************************
6807  Reply to a printclose.
6808 ****************************************************************************/
6809
6810 void reply_printclose(struct smb_request *req)
6811 {
6812         connection_struct *conn = req->conn;
6813         files_struct *fsp;
6814         NTSTATUS status;
6815
6816         START_PROFILE(SMBsplclose);
6817
6818         if (req->wct < 1) {
6819                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6820                 END_PROFILE(SMBsplclose);
6821                 return;
6822         }
6823
6824         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6825
6826         if (!check_fsp(conn, req, fsp)) {
6827                 END_PROFILE(SMBsplclose);
6828                 return;
6829         }
6830
6831         if (!CAN_PRINT(conn)) {
6832                 reply_force_doserror(req, ERRSRV, ERRerror);
6833                 END_PROFILE(SMBsplclose);
6834                 return;
6835         }
6836
6837         DEBUG(3,("printclose fd=%d %s\n",
6838                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6839
6840         status = close_file(req, fsp, NORMAL_CLOSE);
6841
6842         if(!NT_STATUS_IS_OK(status)) {
6843                 reply_nterror(req, status);
6844                 END_PROFILE(SMBsplclose);
6845                 return;
6846         }
6847
6848         reply_outbuf(req, 0, 0);
6849
6850         END_PROFILE(SMBsplclose);
6851         return;
6852 }
6853
6854 /****************************************************************************
6855  Reply to a printqueue.
6856 ****************************************************************************/
6857
6858 void reply_printqueue(struct smb_request *req)
6859 {
6860         const struct loadparm_substitution *lp_sub =
6861                 loadparm_s3_global_substitution();
6862         connection_struct *conn = req->conn;
6863         int max_count;
6864         int start_index;
6865
6866         START_PROFILE(SMBsplretq);
6867
6868         if (req->wct < 2) {
6869                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6870                 END_PROFILE(SMBsplretq);
6871                 return;
6872         }
6873
6874         max_count = SVAL(req->vwv+0, 0);
6875         start_index = SVAL(req->vwv+1, 0);
6876
6877         /* we used to allow the client to get the cnum wrong, but that
6878            is really quite gross and only worked when there was only
6879            one printer - I think we should now only accept it if they
6880            get it right (tridge) */
6881         if (!CAN_PRINT(conn)) {
6882                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6883                 END_PROFILE(SMBsplretq);
6884                 return;
6885         }
6886
6887         reply_outbuf(req, 2, 3);
6888         SSVAL(req->outbuf,smb_vwv0,0);
6889         SSVAL(req->outbuf,smb_vwv1,0);
6890         SCVAL(smb_buf(req->outbuf),0,1);
6891         SSVAL(smb_buf(req->outbuf),1,0);
6892
6893         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6894                  start_index, max_count));
6895
6896         {
6897                 TALLOC_CTX *mem_ctx = talloc_tos();
6898                 NTSTATUS status;
6899                 WERROR werr;
6900                 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6901                 struct rpc_pipe_client *cli = NULL;
6902                 struct dcerpc_binding_handle *b = NULL;
6903                 struct policy_handle handle;
6904                 struct spoolss_DevmodeContainer devmode_ctr;
6905                 union spoolss_JobInfo *info;
6906                 uint32_t count;
6907                 uint32_t num_to_get;
6908                 uint32_t first;
6909                 uint32_t i;
6910
6911                 ZERO_STRUCT(handle);
6912
6913                 status = rpc_pipe_open_interface(mem_ctx,
6914                                                  &ndr_table_spoolss,
6915                                                  conn->session_info,
6916                                                  conn->sconn->remote_address,
6917                                                  conn->sconn->local_address,
6918                                                  conn->sconn->msg_ctx,
6919                                                  &cli);
6920                 if (!NT_STATUS_IS_OK(status)) {
6921                         DEBUG(0, ("reply_printqueue: "
6922                                   "could not connect to spoolss: %s\n",
6923                                   nt_errstr(status)));
6924                         reply_nterror(req, status);
6925                         goto out;
6926                 }
6927                 b = cli->binding_handle;
6928
6929                 ZERO_STRUCT(devmode_ctr);
6930
6931                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6932                                                 sharename,
6933                                                 NULL, devmode_ctr,
6934                                                 SEC_FLAG_MAXIMUM_ALLOWED,
6935                                                 &handle,
6936                                                 &werr);
6937                 if (!NT_STATUS_IS_OK(status)) {
6938                         reply_nterror(req, status);
6939                         goto out;
6940                 }
6941                 if (!W_ERROR_IS_OK(werr)) {
6942                         reply_nterror(req, werror_to_ntstatus(werr));
6943                         goto out;
6944                 }
6945
6946                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6947                                                &handle,
6948                                                0, /* firstjob */
6949                                                0xff, /* numjobs */
6950                                                2, /* level */
6951                                                0, /* offered */
6952                                                &count,
6953                                                &info);
6954                 if (!W_ERROR_IS_OK(werr)) {
6955                         reply_nterror(req, werror_to_ntstatus(werr));
6956                         goto out;
6957                 }
6958
6959                 if (max_count > 0) {
6960                         first = start_index;
6961                 } else {
6962                         first = start_index + max_count + 1;
6963                 }
6964
6965                 if (first >= count) {
6966                         num_to_get = first;
6967                 } else {
6968                         num_to_get = first + MIN(ABS(max_count), count - first);
6969                 }
6970
6971                 for (i = first; i < num_to_get; i++) {
6972                         char blob[28];
6973                         char *p = blob;
6974                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6975                         int qstatus;
6976                         size_t len = 0;
6977                         uint16_t qrapjobid = pjobid_to_rap(sharename,
6978                                                         info[i].info2.job_id);
6979
6980                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
6981                                 qstatus = 2;
6982                         } else {
6983                                 qstatus = 3;
6984                         }
6985
6986                         srv_put_dos_date2(p, 0, qtime);
6987                         SCVAL(p, 4, qstatus);
6988                         SSVAL(p, 5, qrapjobid);
6989                         SIVAL(p, 7, info[i].info2.size);
6990                         SCVAL(p, 11, 0);
6991                         status = srvstr_push(blob, req->flags2, p+12,
6992                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
6993                         if (!NT_STATUS_IS_OK(status)) {
6994                                 reply_nterror(req, status);
6995                                 goto out;
6996                         }
6997                         if (message_push_blob(
6998                                     &req->outbuf,
6999                                     data_blob_const(
7000                                             blob, sizeof(blob))) == -1) {
7001                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7002                                 goto out;
7003                         }
7004                 }
7005
7006                 if (count > 0) {
7007                         SSVAL(req->outbuf,smb_vwv0,count);
7008                         SSVAL(req->outbuf,smb_vwv1,
7009                               (max_count>0?first+count:first-1));
7010                         SCVAL(smb_buf(req->outbuf),0,1);
7011                         SSVAL(smb_buf(req->outbuf),1,28*count);
7012                 }
7013
7014
7015                 DEBUG(3, ("%u entries returned in queue\n",
7016                           (unsigned)count));
7017
7018 out:
7019                 if (b && is_valid_policy_hnd(&handle)) {
7020                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7021                 }
7022
7023         }
7024
7025         END_PROFILE(SMBsplretq);
7026         return;
7027 }
7028
7029 /****************************************************************************
7030  Reply to a printwrite.
7031 ****************************************************************************/
7032
7033 void reply_printwrite(struct smb_request *req)
7034 {
7035         connection_struct *conn = req->conn;
7036         int numtowrite;
7037         const char *data;
7038         files_struct *fsp;
7039
7040         START_PROFILE(SMBsplwr);
7041
7042         if (req->wct < 1) {
7043                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7044                 END_PROFILE(SMBsplwr);
7045                 return;
7046         }
7047
7048         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7049
7050         if (!check_fsp(conn, req, fsp)) {
7051                 END_PROFILE(SMBsplwr);
7052                 return;
7053         }
7054
7055         if (!fsp->print_file) {
7056                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7057                 END_PROFILE(SMBsplwr);
7058                 return;
7059         }
7060
7061         if (!CHECK_WRITE(fsp)) {
7062                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7063                 END_PROFILE(SMBsplwr);
7064                 return;
7065         }
7066
7067         numtowrite = SVAL(req->buf, 1);
7068
7069         /*
7070          * This already protects us against CVE-2017-12163.
7071          */
7072         if (req->buflen < numtowrite + 3) {
7073                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7074                 END_PROFILE(SMBsplwr);
7075                 return;
7076         }
7077
7078         data = (const char *)req->buf + 3;
7079
7080         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7081                 reply_nterror(req, map_nt_error_from_unix(errno));
7082                 END_PROFILE(SMBsplwr);
7083                 return;
7084         }
7085
7086         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7087
7088         END_PROFILE(SMBsplwr);
7089         return;
7090 }
7091
7092 /****************************************************************************
7093  Reply to a mkdir.
7094 ****************************************************************************/
7095
7096 void reply_mkdir(struct smb_request *req)
7097 {
7098         connection_struct *conn = req->conn;
7099         struct smb_filename *smb_dname = NULL;
7100         char *directory = NULL;
7101         NTSTATUS status;
7102         uint32_t ucf_flags;
7103         TALLOC_CTX *ctx = talloc_tos();
7104
7105         START_PROFILE(SMBmkdir);
7106
7107         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7108                             STR_TERMINATE, &status);
7109         if (!NT_STATUS_IS_OK(status)) {
7110                 reply_nterror(req, status);
7111                 goto out;
7112         }
7113
7114         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7115         status = filename_convert(ctx, conn,
7116                                  directory,
7117                                  ucf_flags,
7118                                  NULL,
7119                                  NULL,
7120                                  &smb_dname);
7121         if (!NT_STATUS_IS_OK(status)) {
7122                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7123                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7124                                         ERRSRV, ERRbadpath);
7125                         goto out;
7126                 }
7127                 reply_nterror(req, status);
7128                 goto out;
7129         }
7130
7131         status = create_directory(conn, req, smb_dname);
7132
7133         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7134
7135         if (!NT_STATUS_IS_OK(status)) {
7136
7137                 if (!use_nt_status()
7138                     && NT_STATUS_EQUAL(status,
7139                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
7140                         /*
7141                          * Yes, in the DOS error code case we get a
7142                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7143                          * samba4 torture test.
7144                          */
7145                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7146                 }
7147
7148                 reply_nterror(req, status);
7149                 goto out;
7150         }
7151
7152         reply_outbuf(req, 0, 0);
7153
7154         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7155  out:
7156         TALLOC_FREE(smb_dname);
7157         END_PROFILE(SMBmkdir);
7158         return;
7159 }
7160
7161 /****************************************************************************
7162  Reply to a rmdir.
7163 ****************************************************************************/
7164
7165 void reply_rmdir(struct smb_request *req)
7166 {
7167         connection_struct *conn = req->conn;
7168         struct smb_filename *smb_dname = NULL;
7169         char *directory = NULL;
7170         NTSTATUS status;
7171         TALLOC_CTX *ctx = talloc_tos();
7172         files_struct *fsp = NULL;
7173         int info = 0;
7174         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7175
7176         START_PROFILE(SMBrmdir);
7177
7178         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7179                             STR_TERMINATE, &status);
7180         if (!NT_STATUS_IS_OK(status)) {
7181                 reply_nterror(req, status);
7182                 goto out;
7183         }
7184
7185         status = filename_convert(ctx, conn,
7186                                  directory,
7187                                  ucf_flags,
7188                                  NULL,
7189                                  NULL,
7190                                  &smb_dname);
7191         if (!NT_STATUS_IS_OK(status)) {
7192                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7193                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7194                                         ERRSRV, ERRbadpath);
7195                         goto out;
7196                 }
7197                 reply_nterror(req, status);
7198                 goto out;
7199         }
7200
7201         if (is_ntfs_stream_smb_fname(smb_dname)) {
7202                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7203                 goto out;
7204         }
7205
7206         status = SMB_VFS_CREATE_FILE(
7207                 conn,                                   /* conn */
7208                 req,                                    /* req */
7209                 0,                                      /* root_dir_fid */
7210                 smb_dname,                              /* fname */
7211                 DELETE_ACCESS,                          /* access_mask */
7212                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7213                         FILE_SHARE_DELETE),
7214                 FILE_OPEN,                              /* create_disposition*/
7215                 FILE_DIRECTORY_FILE,                    /* create_options */
7216                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
7217                 0,                                      /* oplock_request */
7218                 NULL,                                   /* lease */
7219                 0,                                      /* allocation_size */
7220                 0,                                      /* private_flags */
7221                 NULL,                                   /* sd */
7222                 NULL,                                   /* ea_list */
7223                 &fsp,                                   /* result */
7224                 &info,                                  /* pinfo */
7225                 NULL, NULL);                            /* create context */
7226
7227         if (!NT_STATUS_IS_OK(status)) {
7228                 if (open_was_deferred(req->xconn, req->mid)) {
7229                         /* We have re-scheduled this call. */
7230                         goto out;
7231                 }
7232                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7233                         bool ok = defer_smb1_sharing_violation(req);
7234                         if (ok) {
7235                                 goto out;
7236                         }
7237                 }
7238                 reply_nterror(req, status);
7239                 goto out;
7240         }
7241
7242         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7243         if (!NT_STATUS_IS_OK(status)) {
7244                 close_file(req, fsp, ERROR_CLOSE);
7245                 reply_nterror(req, status);
7246                 goto out;
7247         }
7248
7249         if (!set_delete_on_close(fsp, true,
7250                         conn->session_info->security_token,
7251                         conn->session_info->unix_token)) {
7252                 close_file(req, fsp, ERROR_CLOSE);
7253                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7254                 goto out;
7255         }
7256
7257         status = close_file(req, fsp, NORMAL_CLOSE);
7258         if (!NT_STATUS_IS_OK(status)) {
7259                 reply_nterror(req, status);
7260         } else {
7261                 reply_outbuf(req, 0, 0);
7262         }
7263
7264         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7265  out:
7266         TALLOC_FREE(smb_dname);
7267         END_PROFILE(SMBrmdir);
7268         return;
7269 }
7270
7271 /*******************************************************************
7272  Resolve wildcards in a filename rename.
7273 ********************************************************************/
7274
7275 static bool resolve_wildcards(TALLOC_CTX *ctx,
7276                                 const char *name1,
7277                                 const char *name2,
7278                                 char **pp_newname)
7279 {
7280         char *name2_copy = NULL;
7281         char *root1 = NULL;
7282         char *root2 = NULL;
7283         char *ext1 = NULL;
7284         char *ext2 = NULL;
7285         char *p,*p2, *pname1, *pname2;
7286
7287         name2_copy = talloc_strdup(ctx, name2);
7288         if (!name2_copy) {
7289                 return False;
7290         }
7291
7292         pname1 = strrchr_m(name1,'/');
7293         pname2 = strrchr_m(name2_copy,'/');
7294
7295         if (!pname1 || !pname2) {
7296                 return False;
7297         }
7298
7299         /* Truncate the copy of name2 at the last '/' */
7300         *pname2 = '\0';
7301
7302         /* Now go past the '/' */
7303         pname1++;
7304         pname2++;
7305
7306         root1 = talloc_strdup(ctx, pname1);
7307         root2 = talloc_strdup(ctx, pname2);
7308
7309         if (!root1 || !root2) {
7310                 return False;
7311         }
7312
7313         p = strrchr_m(root1,'.');
7314         if (p) {
7315                 *p = 0;
7316                 ext1 = talloc_strdup(ctx, p+1);
7317         } else {
7318                 ext1 = talloc_strdup(ctx, "");
7319         }
7320         p = strrchr_m(root2,'.');
7321         if (p) {
7322                 *p = 0;
7323                 ext2 = talloc_strdup(ctx, p+1);
7324         } else {
7325                 ext2 = talloc_strdup(ctx, "");
7326         }
7327
7328         if (!ext1 || !ext2) {
7329                 return False;
7330         }
7331
7332         p = root1;
7333         p2 = root2;
7334         while (*p2) {
7335                 if (*p2 == '?') {
7336                         /* Hmmm. Should this be mb-aware ? */
7337                         *p2 = *p;
7338                         p2++;
7339                 } else if (*p2 == '*') {
7340                         *p2 = '\0';
7341                         root2 = talloc_asprintf(ctx, "%s%s",
7342                                                 root2,
7343                                                 p);
7344                         if (!root2) {
7345                                 return False;
7346                         }
7347                         break;
7348                 } else {
7349                         p2++;
7350                 }
7351                 if (*p) {
7352                         p++;
7353                 }
7354         }
7355
7356         p = ext1;
7357         p2 = ext2;
7358         while (*p2) {
7359                 if (*p2 == '?') {
7360                         /* Hmmm. Should this be mb-aware ? */
7361                         *p2 = *p;
7362                         p2++;
7363                 } else if (*p2 == '*') {
7364                         *p2 = '\0';
7365                         ext2 = talloc_asprintf(ctx, "%s%s",
7366                                                 ext2,
7367                                                 p);
7368                         if (!ext2) {
7369                                 return False;
7370                         }
7371                         break;
7372                 } else {
7373                         p2++;
7374                 }
7375                 if (*p) {
7376                         p++;
7377                 }
7378         }
7379
7380         if (*ext2) {
7381                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7382                                 name2_copy,
7383                                 root2,
7384                                 ext2);
7385         } else {
7386                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7387                                 name2_copy,
7388                                 root2);
7389         }
7390
7391         if (!*pp_newname) {
7392                 return False;
7393         }
7394
7395         return True;
7396 }
7397
7398 /****************************************************************************
7399  Ensure open files have their names updated. Updated to notify other smbd's
7400  asynchronously.
7401 ****************************************************************************/
7402
7403 static void rename_open_files(connection_struct *conn,
7404                               struct share_mode_lock *lck,
7405                               struct file_id id,
7406                               uint32_t orig_name_hash,
7407                               const struct smb_filename *smb_fname_dst)
7408 {
7409         files_struct *fsp;
7410         bool did_rename = False;
7411         NTSTATUS status;
7412         uint32_t new_name_hash = 0;
7413
7414         for(fsp = file_find_di_first(conn->sconn, id); fsp;
7415             fsp = file_find_di_next(fsp)) {
7416                 struct file_id_buf idbuf;
7417                 /* fsp_name is a relative path under the fsp. To change this for other
7418                    sharepaths we need to manipulate relative paths. */
7419                 /* TODO - create the absolute path and manipulate the newname
7420                    relative to the sharepath. */
7421                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7422                         continue;
7423                 }
7424                 if (fsp->name_hash != orig_name_hash) {
7425                         continue;
7426                 }
7427                 DBG_DEBUG("renaming file %s "
7428                           "(file_id %s) from %s -> %s\n",
7429                           fsp_fnum_dbg(fsp),
7430                           file_id_str_buf(fsp->file_id, &idbuf),
7431                           fsp_str_dbg(fsp),
7432                           smb_fname_str_dbg(smb_fname_dst));
7433
7434                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7435                 if (NT_STATUS_IS_OK(status)) {
7436                         did_rename = True;
7437                         new_name_hash = fsp->name_hash;
7438                 }
7439         }
7440
7441         if (!did_rename) {
7442                 struct file_id_buf idbuf;
7443                 DBG_DEBUG("no open files on file_id %s "
7444                           "for %s\n",
7445                           file_id_str_buf(id, &idbuf),
7446                           smb_fname_str_dbg(smb_fname_dst));
7447         }
7448
7449         /* Send messages to all smbd's (not ourself) that the name has changed. */
7450         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7451                               orig_name_hash, new_name_hash,
7452                               smb_fname_dst);
7453
7454 }
7455
7456 /****************************************************************************
7457  We need to check if the source path is a parent directory of the destination
7458  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7459  refuse the rename with a sharing violation. Under UNIX the above call can
7460  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7461  probably need to check that the client is a Windows one before disallowing
7462  this as a UNIX client (one with UNIX extensions) can know the source is a
7463  symlink and make this decision intelligently. Found by an excellent bug
7464  report from <AndyLiebman@aol.com>.
7465 ****************************************************************************/
7466
7467 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7468                                      const struct smb_filename *smb_fname_dst)
7469 {
7470         const char *psrc = smb_fname_src->base_name;
7471         const char *pdst = smb_fname_dst->base_name;
7472         size_t slen;
7473
7474         if (psrc[0] == '.' && psrc[1] == '/') {
7475                 psrc += 2;
7476         }
7477         if (pdst[0] == '.' && pdst[1] == '/') {
7478                 pdst += 2;
7479         }
7480         if ((slen = strlen(psrc)) > strlen(pdst)) {
7481                 return False;
7482         }
7483         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7484 }
7485
7486 /*
7487  * Do the notify calls from a rename
7488  */
7489
7490 static void notify_rename(connection_struct *conn, bool is_dir,
7491                           const struct smb_filename *smb_fname_src,
7492                           const struct smb_filename *smb_fname_dst)
7493 {
7494         char *parent_dir_src = NULL;
7495         char *parent_dir_dst = NULL;
7496         uint32_t mask;
7497
7498         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7499                 : FILE_NOTIFY_CHANGE_FILE_NAME;
7500
7501         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7502                             &parent_dir_src, NULL) ||
7503             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7504                             &parent_dir_dst, NULL)) {
7505                 goto out;
7506         }
7507
7508         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7509                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7510                              smb_fname_src->base_name);
7511                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7512                              smb_fname_dst->base_name);
7513         }
7514         else {
7515                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7516                              smb_fname_src->base_name);
7517                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7518                              smb_fname_dst->base_name);
7519         }
7520
7521         /* this is a strange one. w2k3 gives an additional event for
7522            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7523            files, but not directories */
7524         if (!is_dir) {
7525                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7526                              FILE_NOTIFY_CHANGE_ATTRIBUTES
7527                              |FILE_NOTIFY_CHANGE_CREATION,
7528                              smb_fname_dst->base_name);
7529         }
7530  out:
7531         TALLOC_FREE(parent_dir_src);
7532         TALLOC_FREE(parent_dir_dst);
7533 }
7534
7535 /****************************************************************************
7536  Returns an error if the parent directory for a filename is open in an
7537  incompatible way.
7538 ****************************************************************************/
7539
7540 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7541                                         const struct smb_filename *smb_fname_dst_in)
7542 {
7543         struct smb_filename *smb_fname_parent = NULL;
7544         struct file_id id;
7545         files_struct *fsp = NULL;
7546         int ret;
7547         bool ok;
7548
7549         ok = parent_smb_fname(talloc_tos(),
7550                               smb_fname_dst_in,
7551                               &smb_fname_parent,
7552                               NULL);
7553         if (!ok) {
7554                 return NT_STATUS_NO_MEMORY;
7555         }
7556
7557         ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7558         if (ret == -1) {
7559                 return map_nt_error_from_unix(errno);
7560         }
7561
7562         /*
7563          * We're only checking on this smbd here, mostly good
7564          * enough.. and will pass tests.
7565          */
7566
7567         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7568         for (fsp = file_find_di_first(conn->sconn, id); fsp;
7569                         fsp = file_find_di_next(fsp)) {
7570                 if (fsp->access_mask & DELETE_ACCESS) {
7571                         return NT_STATUS_SHARING_VIOLATION;
7572                 }
7573         }
7574         return NT_STATUS_OK;
7575 }
7576
7577 /****************************************************************************
7578  Rename an open file - given an fsp.
7579 ****************************************************************************/
7580
7581 NTSTATUS rename_internals_fsp(connection_struct *conn,
7582                         files_struct *fsp,
7583                         const struct smb_filename *smb_fname_dst_in,
7584                         const char *dst_original_lcomp,
7585                         uint32_t attrs,
7586                         bool replace_if_exists)
7587 {
7588         TALLOC_CTX *ctx = talloc_tos();
7589         struct smb_filename *smb_fname_dst = NULL;
7590         NTSTATUS status = NT_STATUS_OK;
7591         struct share_mode_lock *lck = NULL;
7592         uint32_t access_mask = SEC_DIR_ADD_FILE;
7593         bool dst_exists, old_is_stream, new_is_stream;
7594         int ret;
7595
7596         status = check_name(conn, smb_fname_dst_in);
7597         if (!NT_STATUS_IS_OK(status)) {
7598                 return status;
7599         }
7600
7601         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7602         if (!NT_STATUS_IS_OK(status)) {
7603                 return status;
7604         }
7605
7606         if (file_has_open_streams(fsp)) {
7607                 return NT_STATUS_ACCESS_DENIED;
7608         }
7609
7610         /* Make a copy of the dst smb_fname structs */
7611
7612         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7613         if (smb_fname_dst == NULL) {
7614                 status = NT_STATUS_NO_MEMORY;
7615                 goto out;
7616         }
7617
7618         /*
7619          * Check for special case with case preserving and not
7620          * case sensitive. If the new last component differs from the original
7621          * last component only by case, then we should allow
7622          * the rename (user is trying to change the case of the
7623          * filename).
7624          */
7625         if (!conn->case_sensitive && conn->case_preserve &&
7626             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7627             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7628                 char *fname_dst_parent = NULL;
7629                 const char *fname_dst_lcomp = NULL;
7630                 char *orig_lcomp_path = NULL;
7631                 char *orig_lcomp_stream = NULL;
7632                 bool ok = true;
7633
7634                 /*
7635                  * Split off the last component of the processed
7636                  * destination name. We will compare this to
7637                  * the split components of dst_original_lcomp.
7638                  */
7639                 if (!parent_dirname(ctx,
7640                                 smb_fname_dst->base_name,
7641                                 &fname_dst_parent,
7642                                 &fname_dst_lcomp)) {
7643                         status = NT_STATUS_NO_MEMORY;
7644                         goto out;
7645                 }
7646
7647                 /*
7648                  * The dst_original_lcomp component contains
7649                  * the last_component of the path + stream
7650                  * name (if a stream exists).
7651                  *
7652                  * Split off the stream name so we
7653                  * can check them separately.
7654                  */
7655
7656                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7657                         /* POSIX - no stream component. */
7658                         orig_lcomp_path = talloc_strdup(ctx,
7659                                                 dst_original_lcomp);
7660                         if (orig_lcomp_path == NULL) {
7661                                 ok = false;
7662                         }
7663                 } else {
7664                         ok = split_stream_filename(ctx,
7665                                         dst_original_lcomp,
7666                                         &orig_lcomp_path,
7667                                         &orig_lcomp_stream);
7668                 }
7669
7670                 if (!ok) {
7671                         TALLOC_FREE(fname_dst_parent);
7672                         status = NT_STATUS_NO_MEMORY;
7673                         goto out;
7674                 }
7675
7676                 /* If the base names only differ by case, use original. */
7677                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7678                         char *tmp;
7679                         /*
7680                          * Replace the modified last component with the
7681                          * original.
7682                          */
7683                         if (!ISDOT(fname_dst_parent)) {
7684                                 tmp = talloc_asprintf(smb_fname_dst,
7685                                         "%s/%s",
7686                                         fname_dst_parent,
7687                                         orig_lcomp_path);
7688                         } else {
7689                                 tmp = talloc_strdup(smb_fname_dst,
7690                                         orig_lcomp_path);
7691                         }
7692                         if (tmp == NULL) {
7693                                 status = NT_STATUS_NO_MEMORY;
7694                                 TALLOC_FREE(fname_dst_parent);
7695                                 TALLOC_FREE(orig_lcomp_path);
7696                                 TALLOC_FREE(orig_lcomp_stream);
7697                                 goto out;
7698                         }
7699                         TALLOC_FREE(smb_fname_dst->base_name);
7700                         smb_fname_dst->base_name = tmp;
7701                 }
7702
7703                 /* If the stream_names only differ by case, use original. */
7704                 if(!strcsequal(smb_fname_dst->stream_name,
7705                                orig_lcomp_stream)) {
7706                         /* Use the original stream. */
7707                         char *tmp = talloc_strdup(smb_fname_dst,
7708                                             orig_lcomp_stream);
7709                         if (tmp == NULL) {
7710                                 status = NT_STATUS_NO_MEMORY;
7711                                 TALLOC_FREE(fname_dst_parent);
7712                                 TALLOC_FREE(orig_lcomp_path);
7713                                 TALLOC_FREE(orig_lcomp_stream);
7714                                 goto out;
7715                         }
7716                         TALLOC_FREE(smb_fname_dst->stream_name);
7717                         smb_fname_dst->stream_name = tmp;
7718                 }
7719                 TALLOC_FREE(fname_dst_parent);
7720                 TALLOC_FREE(orig_lcomp_path);
7721                 TALLOC_FREE(orig_lcomp_stream);
7722         }
7723
7724         /*
7725          * If the src and dest names are identical - including case,
7726          * don't do the rename, just return success.
7727          */
7728
7729         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7730             strcsequal(fsp->fsp_name->stream_name,
7731                        smb_fname_dst->stream_name)) {
7732                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7733                           "- returning success\n",
7734                           smb_fname_str_dbg(smb_fname_dst)));
7735                 status = NT_STATUS_OK;
7736                 goto out;
7737         }
7738
7739         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7740         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7741
7742         /* Return the correct error code if both names aren't streams. */
7743         if (!old_is_stream && new_is_stream) {
7744                 status = NT_STATUS_OBJECT_NAME_INVALID;
7745                 goto out;
7746         }
7747
7748         if (old_is_stream && !new_is_stream) {
7749                 status = NT_STATUS_INVALID_PARAMETER;
7750                 goto out;
7751         }
7752
7753         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7754
7755         if(!replace_if_exists && dst_exists) {
7756                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7757                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7758                           smb_fname_str_dbg(smb_fname_dst)));
7759                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7760                 goto out;
7761         }
7762
7763         if (dst_exists) {
7764                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7765                     &smb_fname_dst->st);
7766                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7767                                                            fileid);
7768                 /* The file can be open when renaming a stream */
7769                 if (dst_fsp && !new_is_stream) {
7770                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7771                         status = NT_STATUS_ACCESS_DENIED;
7772                         goto out;
7773                 }
7774         }
7775
7776         /* Ensure we have a valid stat struct for the source. */
7777         status = vfs_stat_fsp(fsp);
7778         if (!NT_STATUS_IS_OK(status)) {
7779                 goto out;
7780         }
7781
7782         status = can_rename(conn, fsp, attrs);
7783
7784         if (!NT_STATUS_IS_OK(status)) {
7785                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7786                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7787                           smb_fname_str_dbg(smb_fname_dst)));
7788                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7789                         status = NT_STATUS_ACCESS_DENIED;
7790                 goto out;
7791         }
7792
7793         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7794                 status = NT_STATUS_ACCESS_DENIED;
7795                 goto out;
7796         }
7797
7798         /* Do we have rights to move into the destination ? */
7799         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7800                 /* We're moving a directory. */
7801                 access_mask = SEC_DIR_ADD_SUBDIR;
7802         }
7803         status = check_parent_access(conn,
7804                                 smb_fname_dst,
7805                                 access_mask);
7806         if (!NT_STATUS_IS_OK(status)) {
7807                 DBG_INFO("check_parent_access on "
7808                         "dst %s returned %s\n",
7809                         smb_fname_str_dbg(smb_fname_dst),
7810                         nt_errstr(status));
7811                 goto out;
7812         }
7813
7814         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7815
7816         /*
7817          * We have the file open ourselves, so not being able to get the
7818          * corresponding share mode lock is a fatal error.
7819          */
7820
7821         SMB_ASSERT(lck != NULL);
7822
7823         ret = SMB_VFS_RENAMEAT(conn,
7824                         conn->cwd_fsp,
7825                         fsp->fsp_name,
7826                         conn->cwd_fsp,
7827                         smb_fname_dst);
7828         if (ret == 0) {
7829                 uint32_t create_options = fsp->fh->private_options;
7830
7831                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7832                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7833                           smb_fname_str_dbg(smb_fname_dst)));
7834
7835                 if (!fsp->fsp_flags.is_directory &&
7836                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7837                     (lp_map_archive(SNUM(conn)) ||
7838                     lp_store_dos_attributes(SNUM(conn)))) {
7839                         /* We must set the archive bit on the newly
7840                            renamed file. */
7841                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7842                                 uint32_t old_dosmode = dos_mode(conn,
7843                                                         smb_fname_dst);
7844                                 file_set_dosmode(conn,
7845                                         smb_fname_dst,
7846                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7847                                         NULL,
7848                                         true);
7849                         }
7850                 }
7851
7852                 notify_rename(conn,
7853                               fsp->fsp_flags.is_directory,
7854                               fsp->fsp_name,
7855                               smb_fname_dst);
7856
7857                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7858                                   smb_fname_dst);
7859
7860                 /*
7861                  * A rename acts as a new file create w.r.t. allowing an initial delete
7862                  * on close, probably because in Windows there is a new handle to the
7863                  * new file. If initial delete on close was requested but not
7864                  * originally set, we need to set it here. This is probably not 100% correct,
7865                  * but will work for the CIFSFS client which in non-posix mode
7866                  * depends on these semantics. JRA.
7867                  */
7868
7869                 if (create_options & FILE_DELETE_ON_CLOSE) {
7870                         status = can_set_delete_on_close(fsp, 0);
7871
7872                         if (NT_STATUS_IS_OK(status)) {
7873                                 /* Note that here we set the *initial* delete on close flag,
7874                                  * not the regular one. The magic gets handled in close. */
7875                                 fsp->fsp_flags.initial_delete_on_close = true;
7876                         }
7877                 }
7878                 TALLOC_FREE(lck);
7879                 status = NT_STATUS_OK;
7880                 goto out;
7881         }
7882
7883         TALLOC_FREE(lck);
7884
7885         if (errno == ENOTDIR || errno == EISDIR) {
7886                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7887         } else {
7888                 status = map_nt_error_from_unix(errno);
7889         }
7890
7891         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7892                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7893                   smb_fname_str_dbg(smb_fname_dst)));
7894
7895  out:
7896         TALLOC_FREE(smb_fname_dst);
7897
7898         return status;
7899 }
7900
7901 /****************************************************************************
7902  The guts of the rename command, split out so it may be called by the NT SMB
7903  code.
7904 ****************************************************************************/
7905
7906 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7907                         connection_struct *conn,
7908                         struct smb_request *req,
7909                         struct smb_filename *smb_fname_src,
7910                         struct smb_filename *smb_fname_dst,
7911                         const char *dst_original_lcomp,
7912                         uint32_t attrs,
7913                         bool replace_if_exists,
7914                         bool src_has_wild,
7915                         bool dest_has_wild,
7916                         uint32_t access_mask)
7917 {
7918         char *fname_src_dir = NULL;
7919         struct smb_filename *smb_fname_src_dir = NULL;
7920         char *fname_src_mask = NULL;
7921         int count=0;
7922         NTSTATUS status = NT_STATUS_OK;
7923         struct smb_Dir *dir_hnd = NULL;
7924         const char *dname = NULL;
7925         char *talloced = NULL;
7926         long offset = 0;
7927         int create_options = 0;
7928         bool posix_pathnames = (req != NULL && req->posix_pathnames);
7929         struct smb2_create_blobs *posx = NULL;
7930         int rc;
7931
7932         /*
7933          * Split the old name into directory and last component
7934          * strings. Note that unix_convert may have stripped off a
7935          * leading ./ from both name and newname if the rename is
7936          * at the root of the share. We need to make sure either both
7937          * name and newname contain a / character or neither of them do
7938          * as this is checked in resolve_wildcards().
7939          */
7940
7941         /* Split up the directory from the filename/mask. */
7942         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7943                                       &fname_src_dir, &fname_src_mask);
7944         if (!NT_STATUS_IS_OK(status)) {
7945                 status = NT_STATUS_NO_MEMORY;
7946                 goto out;
7947         }
7948
7949         /*
7950          * We should only check the mangled cache
7951          * here if unix_convert failed. This means
7952          * that the path in 'mask' doesn't exist
7953          * on the file system and so we need to look
7954          * for a possible mangle. This patch from
7955          * Tine Smukavec <valentin.smukavec@hermes.si>.
7956          */
7957
7958         if (!VALID_STAT(smb_fname_src->st) &&
7959             mangle_is_mangled(fname_src_mask, conn->params)) {
7960                 char *new_mask = NULL;
7961                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7962                                             conn->params);
7963                 if (new_mask) {
7964                         TALLOC_FREE(fname_src_mask);
7965                         fname_src_mask = new_mask;
7966                 }
7967         }
7968
7969         if (posix_pathnames) {
7970                 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7971                 if (!NT_STATUS_IS_OK(status)) {
7972                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7973                                     nt_errstr(status));
7974                         goto out;
7975                 }
7976         }
7977
7978         if (!src_has_wild) {
7979                 files_struct *fsp;
7980
7981                 /*
7982                  * Only one file needs to be renamed. Append the mask back
7983                  * onto the directory.
7984                  */
7985                 TALLOC_FREE(smb_fname_src->base_name);
7986                 if (ISDOT(fname_src_dir)) {
7987                         /* Ensure we use canonical names on open. */
7988                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7989                                                         "%s",
7990                                                         fname_src_mask);
7991                 } else {
7992                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7993                                                         "%s/%s",
7994                                                         fname_src_dir,
7995                                                         fname_src_mask);
7996                 }
7997                 if (!smb_fname_src->base_name) {
7998                         status = NT_STATUS_NO_MEMORY;
7999                         goto out;
8000                 }
8001
8002                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8003                           "case_preserve = %d, short case preserve = %d, "
8004                           "directory = %s, newname = %s, "
8005                           "last_component_dest = %s\n",
8006                           conn->case_sensitive, conn->case_preserve,
8007                           conn->short_case_preserve,
8008                           smb_fname_str_dbg(smb_fname_src),
8009                           smb_fname_str_dbg(smb_fname_dst),
8010                           dst_original_lcomp));
8011
8012                 /* The dest name still may have wildcards. */
8013                 if (dest_has_wild) {
8014                         char *fname_dst_mod = NULL;
8015                         if (!resolve_wildcards(smb_fname_dst,
8016                                                smb_fname_src->base_name,
8017                                                smb_fname_dst->base_name,
8018                                                &fname_dst_mod)) {
8019                                 DEBUG(6, ("rename_internals: resolve_wildcards "
8020                                           "%s %s failed\n",
8021                                           smb_fname_src->base_name,
8022                                           smb_fname_dst->base_name));
8023                                 status = NT_STATUS_NO_MEMORY;
8024                                 goto out;
8025                         }
8026                         TALLOC_FREE(smb_fname_dst->base_name);
8027                         smb_fname_dst->base_name = fname_dst_mod;
8028                 }
8029
8030                 ZERO_STRUCT(smb_fname_src->st);
8031                 if (posix_pathnames) {
8032                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8033                 } else {
8034                         rc = SMB_VFS_STAT(conn, smb_fname_src);
8035                 }
8036                 if (rc == -1) {
8037                         status = map_nt_error_from_unix_common(errno);
8038                         goto out;
8039                 }
8040
8041                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8042                         create_options |= FILE_DIRECTORY_FILE;
8043                 }
8044
8045                 status = SMB_VFS_CREATE_FILE(
8046                         conn,                           /* conn */
8047                         req,                            /* req */
8048                         0,                              /* root_dir_fid */
8049                         smb_fname_src,                  /* fname */
8050                         access_mask,                    /* access_mask */
8051                         (FILE_SHARE_READ |              /* share_access */
8052                             FILE_SHARE_WRITE),
8053                         FILE_OPEN,                      /* create_disposition*/
8054                         create_options,                 /* create_options */
8055                         0,                              /* file_attributes */
8056                         0,                              /* oplock_request */
8057                         NULL,                           /* lease */
8058                         0,                              /* allocation_size */
8059                         0,                              /* private_flags */
8060                         NULL,                           /* sd */
8061                         NULL,                           /* ea_list */
8062                         &fsp,                           /* result */
8063                         NULL,                           /* pinfo */
8064                         posx,                           /* in_context_blobs */
8065                         NULL);                          /* out_context_blobs */
8066
8067                 if (!NT_STATUS_IS_OK(status)) {
8068                         DEBUG(3, ("Could not open rename source %s: %s\n",
8069                                   smb_fname_str_dbg(smb_fname_src),
8070                                   nt_errstr(status)));
8071                         goto out;
8072                 }
8073
8074                 status = rename_internals_fsp(conn,
8075                                         fsp,
8076                                         smb_fname_dst,
8077                                         dst_original_lcomp,
8078                                         attrs,
8079                                         replace_if_exists);
8080
8081                 close_file(req, fsp, NORMAL_CLOSE);
8082
8083                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8084                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8085                           smb_fname_str_dbg(smb_fname_dst)));
8086
8087                 goto out;
8088         }
8089
8090         /*
8091          * Wildcards - process each file that matches.
8092          */
8093         if (strequal(fname_src_mask, "????????.???")) {
8094                 TALLOC_FREE(fname_src_mask);
8095                 fname_src_mask = talloc_strdup(ctx, "*");
8096                 if (!fname_src_mask) {
8097                         status = NT_STATUS_NO_MEMORY;
8098                         goto out;
8099                 }
8100         }
8101
8102         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8103                                 fname_src_dir,
8104                                 NULL,
8105                                 NULL,
8106                                 smb_fname_src->flags);
8107         if (smb_fname_src_dir == NULL) {
8108                 status = NT_STATUS_NO_MEMORY;
8109                 goto out;
8110         }
8111
8112         status = check_name(conn, smb_fname_src_dir);
8113         if (!NT_STATUS_IS_OK(status)) {
8114                 goto out;
8115         }
8116
8117         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8118                           attrs);
8119         if (dir_hnd == NULL) {
8120                 status = map_nt_error_from_unix(errno);
8121                 goto out;
8122         }
8123
8124         status = NT_STATUS_NO_SUCH_FILE;
8125         /*
8126          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8127          * - gentest fix. JRA
8128          */
8129
8130         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8131                                     &talloced))) {
8132                 files_struct *fsp = NULL;
8133                 char *destname = NULL;
8134                 bool sysdir_entry = False;
8135
8136                 /* Quick check for "." and ".." */
8137                 if (ISDOT(dname) || ISDOTDOT(dname)) {
8138                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8139                                 sysdir_entry = True;
8140                         } else {
8141                                 TALLOC_FREE(talloced);
8142                                 continue;
8143                         }
8144                 }
8145
8146                 if (!is_visible_file(conn, smb_fname_src_dir, dname,
8147                                      &smb_fname_src->st, false)) {
8148                         TALLOC_FREE(talloced);
8149                         continue;
8150                 }
8151
8152                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8153                         TALLOC_FREE(talloced);
8154                         continue;
8155                 }
8156
8157                 if (sysdir_entry) {
8158                         status = NT_STATUS_OBJECT_NAME_INVALID;
8159                         break;
8160                 }
8161
8162                 TALLOC_FREE(smb_fname_src->base_name);
8163                 if (ISDOT(fname_src_dir)) {
8164                         /* Ensure we use canonical names on open. */
8165                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8166                                                         "%s",
8167                                                         dname);
8168                 } else {
8169                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8170                                                         "%s/%s",
8171                                                         fname_src_dir,
8172                                                         dname);
8173                 }
8174                 if (!smb_fname_src->base_name) {
8175                         status = NT_STATUS_NO_MEMORY;
8176                         goto out;
8177                 }
8178
8179                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8180                                        smb_fname_dst->base_name,
8181                                        &destname)) {
8182                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
8183                                   smb_fname_src->base_name, destname));
8184                         TALLOC_FREE(talloced);
8185                         continue;
8186                 }
8187                 if (!destname) {
8188                         status = NT_STATUS_NO_MEMORY;
8189                         goto out;
8190                 }
8191
8192                 TALLOC_FREE(smb_fname_dst->base_name);
8193                 smb_fname_dst->base_name = destname;
8194
8195                 ZERO_STRUCT(smb_fname_src->st);
8196                 if (posix_pathnames) {
8197                         SMB_VFS_LSTAT(conn, smb_fname_src);
8198                 } else {
8199                         SMB_VFS_STAT(conn, smb_fname_src);
8200                 }
8201
8202                 create_options = 0;
8203
8204                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8205                         create_options |= FILE_DIRECTORY_FILE;
8206                 }
8207
8208                 status = SMB_VFS_CREATE_FILE(
8209                         conn,                           /* conn */
8210                         req,                            /* req */
8211                         0,                              /* root_dir_fid */
8212                         smb_fname_src,                  /* fname */
8213                         access_mask,                    /* access_mask */
8214                         (FILE_SHARE_READ |              /* share_access */
8215                             FILE_SHARE_WRITE),
8216                         FILE_OPEN,                      /* create_disposition*/
8217                         create_options,                 /* create_options */
8218                         0,                              /* file_attributes */
8219                         0,                              /* oplock_request */
8220                         NULL,                           /* lease */
8221                         0,                              /* allocation_size */
8222                         0,                              /* private_flags */
8223                         NULL,                           /* sd */
8224                         NULL,                           /* ea_list */
8225                         &fsp,                           /* result */
8226                         NULL,                           /* pinfo */
8227                         posx,                           /* in_context_blobs */
8228                         NULL);                          /* out_context_blobs */
8229
8230                 if (!NT_STATUS_IS_OK(status)) {
8231                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8232                                  "returned %s rename %s -> %s\n",
8233                                  nt_errstr(status),
8234                                  smb_fname_str_dbg(smb_fname_src),
8235                                  smb_fname_str_dbg(smb_fname_dst)));
8236                         break;
8237                 }
8238
8239                 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8240                 if (dst_original_lcomp == NULL) {
8241                         status = NT_STATUS_NO_MEMORY;
8242                         goto out;
8243                 }
8244
8245                 status = rename_internals_fsp(conn,
8246                                         fsp,
8247                                         smb_fname_dst,
8248                                         dst_original_lcomp,
8249                                         attrs,
8250                                         replace_if_exists);
8251
8252                 close_file(req, fsp, NORMAL_CLOSE);
8253
8254                 if (!NT_STATUS_IS_OK(status)) {
8255                         DEBUG(3, ("rename_internals_fsp returned %s for "
8256                                   "rename %s -> %s\n", nt_errstr(status),
8257                                   smb_fname_str_dbg(smb_fname_src),
8258                                   smb_fname_str_dbg(smb_fname_dst)));
8259                         break;
8260                 }
8261
8262                 count++;
8263
8264                 DEBUG(3,("rename_internals: doing rename on %s -> "
8265                          "%s\n", smb_fname_str_dbg(smb_fname_src),
8266                          smb_fname_str_dbg(smb_fname_src)));
8267                 TALLOC_FREE(talloced);
8268         }
8269         TALLOC_FREE(dir_hnd);
8270
8271         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8272                 status = map_nt_error_from_unix(errno);
8273         }
8274
8275  out:
8276         TALLOC_FREE(posx);
8277         TALLOC_FREE(talloced);
8278         TALLOC_FREE(smb_fname_src_dir);
8279         TALLOC_FREE(fname_src_dir);
8280         TALLOC_FREE(fname_src_mask);
8281         return status;
8282 }
8283
8284 /****************************************************************************
8285  Reply to a mv.
8286 ****************************************************************************/
8287
8288 void reply_mv(struct smb_request *req)
8289 {
8290         connection_struct *conn = req->conn;
8291         char *name = NULL;
8292         char *newname = NULL;
8293         const char *p;
8294         uint32_t attrs;
8295         NTSTATUS status;
8296         bool src_has_wcard = False;
8297         bool dest_has_wcard = False;
8298         TALLOC_CTX *ctx = talloc_tos();
8299         struct smb_filename *smb_fname_src = NULL;
8300         struct smb_filename *smb_fname_dst = NULL;
8301         const char *dst_original_lcomp = NULL;
8302         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8303                 (req->posix_pathnames ?
8304                         UCF_UNIX_NAME_LOOKUP :
8305                         UCF_COND_ALLOW_WCARD_LCOMP);
8306         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8307                 (req->posix_pathnames ?
8308                         0 :
8309                         UCF_COND_ALLOW_WCARD_LCOMP);
8310         bool stream_rename = false;
8311
8312         START_PROFILE(SMBmv);
8313
8314         if (req->wct < 1) {
8315                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8316                 goto out;
8317         }
8318
8319         attrs = SVAL(req->vwv+0, 0);
8320
8321         p = (const char *)req->buf + 1;
8322         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8323                                        &status, &src_has_wcard);
8324         if (!NT_STATUS_IS_OK(status)) {
8325                 reply_nterror(req, status);
8326                 goto out;
8327         }
8328         p++;
8329         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8330                                        &status, &dest_has_wcard);
8331         if (!NT_STATUS_IS_OK(status)) {
8332                 reply_nterror(req, status);
8333                 goto out;
8334         }
8335
8336         if (!req->posix_pathnames) {
8337                 /* The newname must begin with a ':' if the
8338                    name contains a ':'. */
8339                 if (strchr_m(name, ':')) {
8340                         if (newname[0] != ':') {
8341                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8342                                 goto out;
8343                         }
8344                         stream_rename = true;
8345                 }
8346         }
8347
8348         status = filename_convert(ctx,
8349                                   conn,
8350                                   name,
8351                                   src_ucf_flags,
8352                                   NULL,
8353                                   &src_has_wcard,
8354                                   &smb_fname_src);
8355
8356         if (!NT_STATUS_IS_OK(status)) {
8357                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8358                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8359                                         ERRSRV, ERRbadpath);
8360                         goto out;
8361                 }
8362                 reply_nterror(req, status);
8363                 goto out;
8364         }
8365
8366         status = filename_convert(ctx,
8367                                   conn,
8368                                   newname,
8369                                   dst_ucf_flags,
8370                                   NULL,
8371                                   &dest_has_wcard,
8372                                   &smb_fname_dst);
8373
8374         if (!NT_STATUS_IS_OK(status)) {
8375                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8376                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8377                                         ERRSRV, ERRbadpath);
8378                         goto out;
8379                 }
8380                 reply_nterror(req, status);
8381                 goto out;
8382         }
8383
8384         /* Get the last component of the destination for rename_internals(). */
8385         dst_original_lcomp = get_original_lcomp(ctx,
8386                                         conn,
8387                                         newname,
8388                                         dst_ucf_flags);
8389         if (dst_original_lcomp == NULL) {
8390                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8391                 goto out;
8392         }
8393
8394         if (stream_rename) {
8395                 /* smb_fname_dst->base_name must be the same as
8396                    smb_fname_src->base_name. */
8397                 TALLOC_FREE(smb_fname_dst->base_name);
8398                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8399                                                 smb_fname_src->base_name);
8400                 if (!smb_fname_dst->base_name) {
8401                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8402                         goto out;
8403                 }
8404         }
8405
8406         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8407                  smb_fname_str_dbg(smb_fname_dst)));
8408
8409         status = rename_internals(ctx,
8410                                 conn,
8411                                 req,
8412                                 smb_fname_src,
8413                                 smb_fname_dst,
8414                                 dst_original_lcomp,
8415                                 attrs,
8416                                 false,
8417                                 src_has_wcard,
8418                                 dest_has_wcard,
8419                                 DELETE_ACCESS);
8420         if (!NT_STATUS_IS_OK(status)) {
8421                 if (open_was_deferred(req->xconn, req->mid)) {
8422                         /* We have re-scheduled this call. */
8423                         goto out;
8424                 }
8425                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8426                         bool ok = defer_smb1_sharing_violation(req);
8427                         if (ok) {
8428                                 goto out;
8429                         }
8430                 }
8431                 reply_nterror(req, status);
8432                 goto out;
8433         }
8434
8435         reply_outbuf(req, 0, 0);
8436  out:
8437         TALLOC_FREE(smb_fname_src);
8438         TALLOC_FREE(smb_fname_dst);
8439         END_PROFILE(SMBmv);
8440         return;
8441 }
8442
8443 /*******************************************************************
8444  Copy a file as part of a reply_copy.
8445 ******************************************************************/
8446
8447 /*
8448  * TODO: check error codes on all callers
8449  */
8450
8451 NTSTATUS copy_file(TALLOC_CTX *ctx,
8452                         connection_struct *conn,
8453                         struct smb_filename *smb_fname_src,
8454                         struct smb_filename *smb_fname_dst,
8455                         int ofun,
8456                         int count,
8457                         bool target_is_directory)
8458 {
8459         struct smb_filename *smb_fname_dst_tmp = NULL;
8460         off_t ret=-1;
8461         files_struct *fsp1,*fsp2;
8462         uint32_t dosattrs;
8463         uint32_t new_create_disposition;
8464         NTSTATUS status;
8465
8466
8467         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8468         if (smb_fname_dst_tmp == NULL) {
8469                 return NT_STATUS_NO_MEMORY;
8470         }
8471
8472         /*
8473          * If the target is a directory, extract the last component from the
8474          * src filename and append it to the dst filename
8475          */
8476         if (target_is_directory) {
8477                 const char *p;
8478
8479                 /* dest/target can't be a stream if it's a directory. */
8480                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8481
8482                 p = strrchr_m(smb_fname_src->base_name,'/');
8483                 if (p) {
8484                         p++;
8485                 } else {
8486                         p = smb_fname_src->base_name;
8487                 }
8488                 smb_fname_dst_tmp->base_name =
8489                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8490                                            p);
8491                 if (!smb_fname_dst_tmp->base_name) {
8492                         status = NT_STATUS_NO_MEMORY;
8493                         goto out;
8494                 }
8495         }
8496
8497         status = vfs_file_exist(conn, smb_fname_src);
8498         if (!NT_STATUS_IS_OK(status)) {
8499                 goto out;
8500         }
8501
8502         if (!target_is_directory && count) {
8503                 new_create_disposition = FILE_OPEN;
8504         } else {
8505                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8506                                                  0, ofun,
8507                                                  NULL, NULL,
8508                                                  &new_create_disposition,
8509                                                  NULL,
8510                                                  NULL)) {
8511                         status = NT_STATUS_INVALID_PARAMETER;
8512                         goto out;
8513                 }
8514         }
8515
8516         /* Open the src file for reading. */
8517         status = SMB_VFS_CREATE_FILE(
8518                 conn,                                   /* conn */
8519                 NULL,                                   /* req */
8520                 0,                                      /* root_dir_fid */
8521                 smb_fname_src,                          /* fname */
8522                 FILE_GENERIC_READ,                      /* access_mask */
8523                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8524                 FILE_OPEN,                              /* create_disposition*/
8525                 0,                                      /* create_options */
8526                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
8527                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8528                 NULL,                                   /* lease */
8529                 0,                                      /* allocation_size */
8530                 0,                                      /* private_flags */
8531                 NULL,                                   /* sd */
8532                 NULL,                                   /* ea_list */
8533                 &fsp1,                                  /* result */
8534                 NULL,                                   /* psbuf */
8535                 NULL, NULL);                            /* create context */
8536
8537         if (!NT_STATUS_IS_OK(status)) {
8538                 goto out;
8539         }
8540
8541         dosattrs = dos_mode(conn, smb_fname_src);
8542
8543         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8544                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8545         }
8546
8547         /* Open the dst file for writing. */
8548         status = SMB_VFS_CREATE_FILE(
8549                 conn,                                   /* conn */
8550                 NULL,                                   /* req */
8551                 0,                                      /* root_dir_fid */
8552                 smb_fname_dst,                          /* fname */
8553                 FILE_GENERIC_WRITE,                     /* access_mask */
8554                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8555                 new_create_disposition,                 /* create_disposition*/
8556                 0,                                      /* create_options */
8557                 dosattrs,                               /* file_attributes */
8558                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8559                 NULL,                                   /* lease */
8560                 0,                                      /* allocation_size */
8561                 0,                                      /* private_flags */
8562                 NULL,                                   /* sd */
8563                 NULL,                                   /* ea_list */
8564                 &fsp2,                                  /* result */
8565                 NULL,                                   /* psbuf */
8566                 NULL, NULL);                            /* create context */
8567
8568         if (!NT_STATUS_IS_OK(status)) {
8569                 close_file(NULL, fsp1, ERROR_CLOSE);
8570                 goto out;
8571         }
8572
8573         if (ofun & OPENX_FILE_EXISTS_OPEN) {
8574                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8575                 if (ret == -1) {
8576                         DEBUG(0, ("error - vfs lseek returned error %s\n",
8577                                 strerror(errno)));
8578                         status = map_nt_error_from_unix(errno);
8579                         close_file(NULL, fsp1, ERROR_CLOSE);
8580                         close_file(NULL, fsp2, ERROR_CLOSE);
8581                         goto out;
8582                 }
8583         }
8584
8585         /* Do the actual copy. */
8586         if (smb_fname_src->st.st_ex_size) {
8587                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8588         } else {
8589                 ret = 0;
8590         }
8591
8592         close_file(NULL, fsp1, NORMAL_CLOSE);
8593
8594         /* Ensure the modtime is set correctly on the destination file. */
8595         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8596
8597         /*
8598          * As we are opening fsp1 read-only we only expect
8599          * an error on close on fsp2 if we are out of space.
8600          * Thus we don't look at the error return from the
8601          * close of fsp1.
8602          */
8603         status = close_file(NULL, fsp2, NORMAL_CLOSE);
8604
8605         if (!NT_STATUS_IS_OK(status)) {
8606                 goto out;
8607         }
8608
8609         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8610                 status = NT_STATUS_DISK_FULL;
8611                 goto out;
8612         }
8613
8614         status = NT_STATUS_OK;
8615
8616  out:
8617         TALLOC_FREE(smb_fname_dst_tmp);
8618         return status;
8619 }
8620
8621 /****************************************************************************
8622  Reply to a file copy.
8623 ****************************************************************************/
8624
8625 void reply_copy(struct smb_request *req)
8626 {
8627         connection_struct *conn = req->conn;
8628         struct smb_filename *smb_fname_src = NULL;
8629         struct smb_filename *smb_fname_src_dir = NULL;
8630         struct smb_filename *smb_fname_dst = NULL;
8631         char *fname_src = NULL;
8632         char *fname_dst = NULL;
8633         char *fname_src_mask = NULL;
8634         char *fname_src_dir = NULL;
8635         const char *p;
8636         int count=0;
8637         int error = ERRnoaccess;
8638         int tid2;
8639         int ofun;
8640         int flags;
8641         bool target_is_directory=False;
8642         bool source_has_wild = False;
8643         bool dest_has_wild = False;
8644         NTSTATUS status;
8645         uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8646                 ucf_flags_from_smb_request(req);
8647         uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8648                 ucf_flags_from_smb_request(req);
8649         TALLOC_CTX *ctx = talloc_tos();
8650
8651         START_PROFILE(SMBcopy);
8652
8653         if (req->wct < 3) {
8654                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8655                 goto out;
8656         }
8657
8658         tid2 = SVAL(req->vwv+0, 0);
8659         ofun = SVAL(req->vwv+1, 0);
8660         flags = SVAL(req->vwv+2, 0);
8661
8662         p = (const char *)req->buf;
8663         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8664                                        &status, &source_has_wild);
8665         if (!NT_STATUS_IS_OK(status)) {
8666                 reply_nterror(req, status);
8667                 goto out;
8668         }
8669         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8670                                        &status, &dest_has_wild);
8671         if (!NT_STATUS_IS_OK(status)) {
8672                 reply_nterror(req, status);
8673                 goto out;
8674         }
8675
8676         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8677
8678         if (tid2 != conn->cnum) {
8679                 /* can't currently handle inter share copies XXXX */
8680                 DEBUG(3,("Rejecting inter-share copy\n"));
8681                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8682                 goto out;
8683         }
8684
8685         status = filename_convert(ctx, conn,
8686                                   fname_src,
8687                                   ucf_flags_src,
8688                                   NULL,
8689                                   &source_has_wild,
8690                                   &smb_fname_src);
8691         if (!NT_STATUS_IS_OK(status)) {
8692                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8693                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8694                                         ERRSRV, ERRbadpath);
8695                         goto out;
8696                 }
8697                 reply_nterror(req, status);
8698                 goto out;
8699         }
8700
8701         status = filename_convert(ctx, conn,
8702                                   fname_dst,
8703                                   ucf_flags_dst,
8704                                   NULL,
8705                                   &dest_has_wild,
8706                                   &smb_fname_dst);
8707         if (!NT_STATUS_IS_OK(status)) {
8708                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8709                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8710                                         ERRSRV, ERRbadpath);
8711                         goto out;
8712                 }
8713                 reply_nterror(req, status);
8714                 goto out;
8715         }
8716
8717         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8718
8719         if ((flags&1) && target_is_directory) {
8720                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8721                 goto out;
8722         }
8723
8724         if ((flags&2) && !target_is_directory) {
8725                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8726                 goto out;
8727         }
8728
8729         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8730                 /* wants a tree copy! XXXX */
8731                 DEBUG(3,("Rejecting tree copy\n"));
8732                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8733                 goto out;
8734         }
8735
8736         /* Split up the directory from the filename/mask. */
8737         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8738                                       &fname_src_dir, &fname_src_mask);
8739         if (!NT_STATUS_IS_OK(status)) {
8740                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8741                 goto out;
8742         }
8743
8744         /*
8745          * We should only check the mangled cache
8746          * here if unix_convert failed. This means
8747          * that the path in 'mask' doesn't exist
8748          * on the file system and so we need to look
8749          * for a possible mangle. This patch from
8750          * Tine Smukavec <valentin.smukavec@hermes.si>.
8751          */
8752         if (!VALID_STAT(smb_fname_src->st) &&
8753             mangle_is_mangled(fname_src_mask, conn->params)) {
8754                 char *new_mask = NULL;
8755                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8756                                             &new_mask, conn->params);
8757
8758                 /* Use demangled name if one was successfully found. */
8759                 if (new_mask) {
8760                         TALLOC_FREE(fname_src_mask);
8761                         fname_src_mask = new_mask;
8762                 }
8763         }
8764
8765         if (!source_has_wild) {
8766
8767                 /*
8768                  * Only one file needs to be copied. Append the mask back onto
8769                  * the directory.
8770                  */
8771                 TALLOC_FREE(smb_fname_src->base_name);
8772                 if (ISDOT(fname_src_dir)) {
8773                         /* Ensure we use canonical names on open. */
8774                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8775                                                         "%s",
8776                                                         fname_src_mask);
8777                 } else {
8778                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8779                                                         "%s/%s",
8780                                                         fname_src_dir,
8781                                                         fname_src_mask);
8782                 }
8783                 if (!smb_fname_src->base_name) {
8784                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8785                         goto out;
8786                 }
8787
8788                 if (dest_has_wild) {
8789                         char *fname_dst_mod = NULL;
8790                         if (!resolve_wildcards(smb_fname_dst,
8791                                                smb_fname_src->base_name,
8792                                                smb_fname_dst->base_name,
8793                                                &fname_dst_mod)) {
8794                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8795                                 goto out;
8796                         }
8797                         TALLOC_FREE(smb_fname_dst->base_name);
8798                         smb_fname_dst->base_name = fname_dst_mod;
8799                 }
8800
8801                 status = check_name(conn, smb_fname_src);
8802                 if (!NT_STATUS_IS_OK(status)) {
8803                         reply_nterror(req, status);
8804                         goto out;
8805                 }
8806
8807                 status = check_name(conn, smb_fname_dst);
8808                 if (!NT_STATUS_IS_OK(status)) {
8809                         reply_nterror(req, status);
8810                         goto out;
8811                 }
8812
8813                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8814                                    ofun, count, target_is_directory);
8815
8816                 if(!NT_STATUS_IS_OK(status)) {
8817                         reply_nterror(req, status);
8818                         goto out;
8819                 } else {
8820                         count++;
8821                 }
8822         } else {
8823                 struct smb_Dir *dir_hnd = NULL;
8824                 const char *dname = NULL;
8825                 char *talloced = NULL;
8826                 long offset = 0;
8827
8828                 /*
8829                  * There is a wildcard that requires us to actually read the
8830                  * src dir and copy each file matching the mask to the dst.
8831                  * Right now streams won't be copied, but this could
8832                  * presumably be added with a nested loop for reach dir entry.
8833                  */
8834                 SMB_ASSERT(!smb_fname_src->stream_name);
8835                 SMB_ASSERT(!smb_fname_dst->stream_name);
8836
8837                 smb_fname_src->stream_name = NULL;
8838                 smb_fname_dst->stream_name = NULL;
8839
8840                 if (strequal(fname_src_mask,"????????.???")) {
8841                         TALLOC_FREE(fname_src_mask);
8842                         fname_src_mask = talloc_strdup(ctx, "*");
8843                         if (!fname_src_mask) {
8844                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8845                                 goto out;
8846                         }
8847                 }
8848
8849                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8850                                         fname_src_dir,
8851                                         NULL,
8852                                         NULL,
8853                                         smb_fname_src->flags);
8854                 if (smb_fname_src_dir == NULL) {
8855                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8856                         goto out;
8857                 }
8858
8859                 status = check_name(conn, smb_fname_src_dir);
8860                 if (!NT_STATUS_IS_OK(status)) {
8861                         reply_nterror(req, status);
8862                         goto out;
8863                 }
8864
8865                 dir_hnd = OpenDir(ctx,
8866                                 conn,
8867                                 smb_fname_src_dir,
8868                                 fname_src_mask,
8869                                 0);
8870                 if (dir_hnd == NULL) {
8871                         status = map_nt_error_from_unix(errno);
8872                         reply_nterror(req, status);
8873                         goto out;
8874                 }
8875
8876                 error = ERRbadfile;
8877
8878                 /* Iterate over the src dir copying each entry to the dst. */
8879                 while ((dname = ReadDirName(dir_hnd, &offset,
8880                                             &smb_fname_src->st, &talloced))) {
8881                         char *destname = NULL;
8882
8883                         if (ISDOT(dname) || ISDOTDOT(dname)) {
8884                                 TALLOC_FREE(talloced);
8885                                 continue;
8886                         }
8887
8888                         if (!is_visible_file(conn, smb_fname_src_dir, dname,
8889                                              &smb_fname_src->st, false)) {
8890                                 TALLOC_FREE(talloced);
8891                                 continue;
8892                         }
8893
8894                         if(!mask_match(dname, fname_src_mask,
8895                                        conn->case_sensitive)) {
8896                                 TALLOC_FREE(talloced);
8897                                 continue;
8898                         }
8899
8900                         error = ERRnoaccess;
8901
8902                         /* Get the src smb_fname struct setup. */
8903                         TALLOC_FREE(smb_fname_src->base_name);
8904                         if (ISDOT(fname_src_dir)) {
8905                                 /* Ensure we use canonical names on open. */
8906                                 smb_fname_src->base_name =
8907                                         talloc_asprintf(smb_fname_src, "%s",
8908                                                 dname);
8909                         } else {
8910                                 smb_fname_src->base_name =
8911                                         talloc_asprintf(smb_fname_src, "%s/%s",
8912                                                 fname_src_dir, dname);
8913                         }
8914
8915                         if (!smb_fname_src->base_name) {
8916                                 TALLOC_FREE(dir_hnd);
8917                                 TALLOC_FREE(talloced);
8918                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8919                                 goto out;
8920                         }
8921
8922                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8923                                                smb_fname_dst->base_name,
8924                                                &destname)) {
8925                                 TALLOC_FREE(talloced);
8926                                 continue;
8927                         }
8928                         if (!destname) {
8929                                 TALLOC_FREE(dir_hnd);
8930                                 TALLOC_FREE(talloced);
8931                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8932                                 goto out;
8933                         }
8934
8935                         TALLOC_FREE(smb_fname_dst->base_name);
8936                         smb_fname_dst->base_name = destname;
8937
8938                         status = check_name(conn, smb_fname_src);
8939                         if (!NT_STATUS_IS_OK(status)) {
8940                                 TALLOC_FREE(dir_hnd);
8941                                 TALLOC_FREE(talloced);
8942                                 reply_nterror(req, status);
8943                                 goto out;
8944                         }
8945
8946                         status = check_name(conn, smb_fname_dst);
8947                         if (!NT_STATUS_IS_OK(status)) {
8948                                 TALLOC_FREE(dir_hnd);
8949                                 TALLOC_FREE(talloced);
8950                                 reply_nterror(req, status);
8951                                 goto out;
8952                         }
8953
8954                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8955                                 smb_fname_src->base_name,
8956                                 smb_fname_dst->base_name));
8957
8958                         status = copy_file(ctx, conn, smb_fname_src,
8959                                            smb_fname_dst, ofun, count,
8960                                            target_is_directory);
8961                         if (NT_STATUS_IS_OK(status)) {
8962                                 count++;
8963                         }
8964
8965                         TALLOC_FREE(talloced);
8966                 }
8967                 TALLOC_FREE(dir_hnd);
8968         }
8969
8970         if (count == 0) {
8971                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8972                 goto out;
8973         }
8974
8975         reply_outbuf(req, 1, 0);
8976         SSVAL(req->outbuf,smb_vwv0,count);
8977  out:
8978         TALLOC_FREE(smb_fname_src);
8979         TALLOC_FREE(smb_fname_src_dir);
8980         TALLOC_FREE(smb_fname_dst);
8981         TALLOC_FREE(fname_src);
8982         TALLOC_FREE(fname_dst);
8983         TALLOC_FREE(fname_src_mask);
8984         TALLOC_FREE(fname_src_dir);
8985
8986         END_PROFILE(SMBcopy);
8987         return;
8988 }
8989
8990 #undef DBGC_CLASS
8991 #define DBGC_CLASS DBGC_LOCKING
8992
8993 /****************************************************************************
8994  Get a lock pid, dealing with large count requests.
8995 ****************************************************************************/
8996
8997 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8998                     bool large_file_format)
8999 {
9000         if(!large_file_format)
9001                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9002         else
9003                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9004 }
9005
9006 /****************************************************************************
9007  Get a lock count, dealing with large count requests.
9008 ****************************************************************************/
9009
9010 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9011                         bool large_file_format)
9012 {
9013         uint64_t count = 0;
9014
9015         if(!large_file_format) {
9016                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9017         } else {
9018                 /*
9019                  * No BVAL, this is reversed!
9020                  */
9021                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9022                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9023         }
9024
9025         return count;
9026 }
9027
9028 /****************************************************************************
9029  Get a lock offset, dealing with large offset requests.
9030 ****************************************************************************/
9031
9032 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9033                          bool large_file_format)
9034 {
9035         uint64_t offset = 0;
9036
9037         if(!large_file_format) {
9038                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9039         } else {
9040                 /*
9041                  * No BVAL, this is reversed!
9042                  */
9043                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9044                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9045         }
9046
9047         return offset;
9048 }
9049
9050 struct smbd_do_unlocking_state {
9051         struct files_struct *fsp;
9052         uint16_t num_ulocks;
9053         struct smbd_lock_element *ulocks;
9054         enum brl_flavour lock_flav;
9055         NTSTATUS status;
9056 };
9057
9058 static void smbd_do_unlocking_fn(
9059         TDB_DATA value, bool *pmodified_dependent, void *private_data)
9060 {
9061         struct smbd_do_unlocking_state *state = private_data;
9062         struct files_struct *fsp = state->fsp;
9063         enum brl_flavour lock_flav = state->lock_flav;
9064         uint16_t i;
9065
9066         for (i = 0; i < state->num_ulocks; i++) {
9067                 struct smbd_lock_element *e = &state->ulocks[i];
9068
9069                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9070                           "pid %"PRIu64", file %s\n",
9071                           e->offset,
9072                           e->count,
9073                           e->smblctx,
9074                           fsp_str_dbg(fsp));
9075
9076                 if (e->brltype != UNLOCK_LOCK) {
9077                         /* this can only happen with SMB2 */
9078                         state->status = NT_STATUS_INVALID_PARAMETER;
9079                         return;
9080                 }
9081
9082                 state->status = do_unlock(
9083                         fsp, e->smblctx, e->count, e->offset, lock_flav);
9084
9085                 DBG_DEBUG("do_unlock returned %s\n",
9086                           nt_errstr(state->status));
9087
9088                 if (!NT_STATUS_IS_OK(state->status)) {
9089                         return;
9090                 }
9091         }
9092
9093         *pmodified_dependent = true;
9094 }
9095
9096 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9097                            files_struct *fsp,
9098                            uint16_t num_ulocks,
9099                            struct smbd_lock_element *ulocks,
9100                            enum brl_flavour lock_flav)
9101 {
9102         struct smbd_do_unlocking_state state = {
9103                 .fsp = fsp,
9104                 .num_ulocks = num_ulocks,
9105                 .ulocks = ulocks,
9106                 .lock_flav = lock_flav,
9107         };
9108         NTSTATUS status;
9109
9110         DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9111
9112         status = share_mode_do_locked(
9113                 fsp->file_id, smbd_do_unlocking_fn, &state);
9114
9115         if (!NT_STATUS_IS_OK(status)) {
9116                 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9117                           nt_errstr(status));
9118                 return status;
9119         }
9120         if (!NT_STATUS_IS_OK(state.status)) {
9121                 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9122                           nt_errstr(status));
9123                 return state.status;
9124         }
9125
9126         return NT_STATUS_OK;
9127 }
9128
9129 /****************************************************************************
9130  Reply to a lockingX request.
9131 ****************************************************************************/
9132
9133 static void reply_lockingx_done(struct tevent_req *subreq);
9134
9135 void reply_lockingX(struct smb_request *req)
9136 {
9137         connection_struct *conn = req->conn;
9138         files_struct *fsp;
9139         unsigned char locktype;
9140         enum brl_type brltype;
9141         unsigned char oplocklevel;
9142         uint16_t num_ulocks;
9143         uint16_t num_locks;
9144         int32_t lock_timeout;
9145         uint16_t i;
9146         const uint8_t *data;
9147         bool large_file_format;
9148         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9149         struct smbd_lock_element *locks = NULL;
9150         struct tevent_req *subreq = NULL;
9151
9152         START_PROFILE(SMBlockingX);
9153
9154         if (req->wct < 8) {
9155                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9156                 END_PROFILE(SMBlockingX);
9157                 return;
9158         }
9159
9160         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9161         locktype = CVAL(req->vwv+3, 0);
9162         oplocklevel = CVAL(req->vwv+3, 1);
9163         num_ulocks = SVAL(req->vwv+6, 0);
9164         num_locks = SVAL(req->vwv+7, 0);
9165         lock_timeout = IVAL(req->vwv+4, 0);
9166         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9167
9168         if (!check_fsp(conn, req, fsp)) {
9169                 END_PROFILE(SMBlockingX);
9170                 return;
9171         }
9172
9173         data = req->buf;
9174
9175         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9176                 /* we don't support these - and CANCEL_LOCK makes w2k
9177                    and XP reboot so I don't really want to be
9178                    compatible! (tridge) */
9179                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9180                 END_PROFILE(SMBlockingX);
9181                 return;
9182         }
9183
9184         /* Check if this is an oplock break on a file
9185            we have granted an oplock on.
9186         */
9187         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9188                 /* Client can insist on breaking to none. */
9189                 bool break_to_none = (oplocklevel == 0);
9190                 bool result;
9191
9192                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9193                          "for %s\n", (unsigned int)oplocklevel,
9194                          fsp_fnum_dbg(fsp)));
9195
9196                 /*
9197                  * Make sure we have granted an exclusive or batch oplock on
9198                  * this file.
9199                  */
9200
9201                 if (fsp->oplock_type == 0) {
9202
9203                         /* The Samba4 nbench simulator doesn't understand
9204                            the difference between break to level2 and break
9205                            to none from level2 - it sends oplock break
9206                            replies in both cases. Don't keep logging an error
9207                            message here - just ignore it. JRA. */
9208
9209                         DEBUG(5,("reply_lockingX: Error : oplock break from "
9210                                  "client for %s (oplock=%d) and no "
9211                                  "oplock granted on this file (%s).\n",
9212                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
9213                                  fsp_str_dbg(fsp)));
9214
9215                         /* if this is a pure oplock break request then don't
9216                          * send a reply */
9217                         if (num_locks == 0 && num_ulocks == 0) {
9218                                 END_PROFILE(SMBlockingX);
9219                                 return;
9220                         }
9221
9222                         END_PROFILE(SMBlockingX);
9223                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9224                         return;
9225                 }
9226
9227                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9228                     (break_to_none)) {
9229                         result = remove_oplock(fsp);
9230                 } else {
9231                         result = downgrade_oplock(fsp);
9232                 }
9233
9234                 if (!result) {
9235                         DEBUG(0, ("reply_lockingX: error in removing "
9236                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
9237                         /* Hmmm. Is this panic justified? */
9238                         smb_panic("internal tdb error");
9239                 }
9240
9241                 /* if this is a pure oplock break request then don't send a
9242                  * reply */
9243                 if (num_locks == 0 && num_ulocks == 0) {
9244                         /* Sanity check - ensure a pure oplock break is not a
9245                            chained request. */
9246                         if (CVAL(req->vwv+0, 0) != 0xff) {
9247                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
9248                                          "break is a chained %d request !\n",
9249                                          (unsigned int)CVAL(req->vwv+0, 0)));
9250                         }
9251                         END_PROFILE(SMBlockingX);
9252                         return;
9253                 }
9254         }
9255
9256         if (req->buflen <
9257             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9258                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9259                 END_PROFILE(SMBlockingX);
9260                 return;
9261         }
9262
9263         if (num_ulocks != 0) {
9264                 struct smbd_lock_element *ulocks = NULL;
9265                 bool ok;
9266
9267                 ulocks = talloc_array(
9268                         req, struct smbd_lock_element, num_ulocks);
9269                 if (ulocks == NULL) {
9270                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9271                         END_PROFILE(SMBlockingX);
9272                         return;
9273                 }
9274
9275                 /*
9276                  * Data now points at the beginning of the list of
9277                  * smb_unlkrng structs
9278                  */
9279                 for (i = 0; i < num_ulocks; i++) {
9280                         ulocks[i].req_guid = smbd_request_guid(req,
9281                                 UINT16_MAX - i),
9282                         ulocks[i].smblctx = get_lock_pid(
9283                                 data, i, large_file_format);
9284                         ulocks[i].count = get_lock_count(
9285                                 data, i, large_file_format);
9286                         ulocks[i].offset = get_lock_offset(
9287                                 data, i, large_file_format);
9288                         ulocks[i].brltype = UNLOCK_LOCK;
9289                 }
9290
9291                 /*
9292                  * Unlock cancels pending locks
9293                  */
9294
9295                 ok = smbd_smb1_brl_finish_by_lock(
9296                         fsp,
9297                         large_file_format,
9298                         WINDOWS_LOCK,
9299                         ulocks[0],
9300                         NT_STATUS_OK);
9301                 if (ok) {
9302                         reply_outbuf(req, 2, 0);
9303                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9304                         SSVAL(req->outbuf, smb_vwv1, 0);
9305                         END_PROFILE(SMBlockingX);
9306                         return;
9307                 }
9308
9309                 status = smbd_do_unlocking(
9310                         req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9311                 TALLOC_FREE(ulocks);
9312                 if (!NT_STATUS_IS_OK(status)) {
9313                         END_PROFILE(SMBlockingX);
9314                         reply_nterror(req, status);
9315                         return;
9316                 }
9317         }
9318
9319         /* Now do any requested locks */
9320         data += ((large_file_format ? 20 : 10)*num_ulocks);
9321
9322         /* Data now points at the beginning of the list
9323            of smb_lkrng structs */
9324
9325         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9326                 brltype = READ_LOCK;
9327         } else {
9328                 brltype = WRITE_LOCK;
9329         }
9330
9331         locks = talloc_array(req, struct smbd_lock_element, num_locks);
9332         if (locks == NULL) {
9333                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9334                 END_PROFILE(SMBlockingX);
9335                 return;
9336         }
9337
9338         for (i = 0; i < num_locks; i++) {
9339                 locks[i].req_guid = smbd_request_guid(req, i),
9340                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9341                 locks[i].count = get_lock_count(data, i, large_file_format);
9342                 locks[i].offset = get_lock_offset(data, i, large_file_format);
9343                 locks[i].brltype = brltype;
9344         }
9345
9346         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9347
9348                 bool ok;
9349
9350                 if (num_locks == 0) {
9351                         /* See smbtorture3 lock11 test */
9352                         reply_outbuf(req, 2, 0);
9353                         /* andx chain ends */
9354                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9355                         SSVAL(req->outbuf, smb_vwv1, 0);
9356                         END_PROFILE(SMBlockingX);
9357                         return;
9358                 }
9359
9360                 ok = smbd_smb1_brl_finish_by_lock(
9361                         fsp,
9362                         large_file_format,
9363                         WINDOWS_LOCK,
9364                         locks[0], /* Windows only cancels the first lock */
9365                         NT_STATUS_FILE_LOCK_CONFLICT);
9366
9367                 if (!ok) {
9368                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9369                         END_PROFILE(SMBlockingX);
9370                         return;
9371                 }
9372
9373                 reply_outbuf(req, 2, 0);
9374                 SSVAL(req->outbuf, smb_vwv0, 0xff);
9375                 SSVAL(req->outbuf, smb_vwv1, 0);
9376                 END_PROFILE(SMBlockingX);
9377                 return;
9378         }
9379
9380         subreq = smbd_smb1_do_locks_send(
9381                 fsp,
9382                 req->sconn->ev_ctx,
9383                 &req,
9384                 fsp,
9385                 lock_timeout,
9386                 large_file_format,
9387                 WINDOWS_LOCK,
9388                 num_locks,
9389                 locks);
9390         if (subreq == NULL) {
9391                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9392                 END_PROFILE(SMBlockingX);
9393                 return;
9394         }
9395         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9396         END_PROFILE(SMBlockingX);
9397 }
9398
9399 static void reply_lockingx_done(struct tevent_req *subreq)
9400 {
9401         struct smb_request *req = NULL;
9402         NTSTATUS status;
9403         bool ok;
9404
9405         START_PROFILE(SMBlockingX);
9406
9407         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9408         SMB_ASSERT(ok);
9409
9410         status = smbd_smb1_do_locks_recv(subreq);
9411         TALLOC_FREE(subreq);
9412
9413         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9414
9415         if (NT_STATUS_IS_OK(status)) {
9416                 reply_outbuf(req, 2, 0);
9417                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9418                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
9419         } else {
9420                 reply_nterror(req, status);
9421         }
9422
9423         ok = srv_send_smb(req->xconn,
9424                           (char *)req->outbuf,
9425                           true,
9426                           req->seqnum+1,
9427                           IS_CONN_ENCRYPTED(req->conn),
9428                           NULL);
9429         if (!ok) {
9430                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9431         }
9432         TALLOC_FREE(req);
9433         END_PROFILE(SMBlockingX);
9434 }
9435
9436 #undef DBGC_CLASS
9437 #define DBGC_CLASS DBGC_ALL
9438
9439 /****************************************************************************
9440  Reply to a SMBreadbmpx (read block multiplex) request.
9441  Always reply with an error, if someone has a platform really needs this,
9442  please contact vl@samba.org
9443 ****************************************************************************/
9444
9445 void reply_readbmpx(struct smb_request *req)
9446 {
9447         START_PROFILE(SMBreadBmpx);
9448         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9449         END_PROFILE(SMBreadBmpx);
9450         return;
9451 }
9452
9453 /****************************************************************************
9454  Reply to a SMBreadbs (read block multiplex secondary) request.
9455  Always reply with an error, if someone has a platform really needs this,
9456  please contact vl@samba.org
9457 ****************************************************************************/
9458
9459 void reply_readbs(struct smb_request *req)
9460 {
9461         START_PROFILE(SMBreadBs);
9462         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9463         END_PROFILE(SMBreadBs);
9464         return;
9465 }
9466
9467 /****************************************************************************
9468  Reply to a SMBsetattrE.
9469 ****************************************************************************/
9470
9471 void reply_setattrE(struct smb_request *req)
9472 {
9473         connection_struct *conn = req->conn;
9474         struct smb_file_time ft;
9475         files_struct *fsp;
9476         NTSTATUS status;
9477
9478         START_PROFILE(SMBsetattrE);
9479         init_smb_file_time(&ft);
9480
9481         if (req->wct < 7) {
9482                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9483                 goto out;
9484         }
9485
9486         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9487
9488         if(!fsp || (fsp->conn != conn)) {
9489                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9490                 goto out;
9491         }
9492
9493         /*
9494          * Convert the DOS times into unix times.
9495          */
9496
9497         ft.atime = time_t_to_full_timespec(
9498             srv_make_unix_date2(req->vwv+3));
9499         ft.mtime = time_t_to_full_timespec(
9500             srv_make_unix_date2(req->vwv+5));
9501         ft.create_time = time_t_to_full_timespec(
9502             srv_make_unix_date2(req->vwv+1));
9503
9504         reply_outbuf(req, 0, 0);
9505
9506         /* 
9507          * Patch from Ray Frush <frush@engr.colostate.edu>
9508          * Sometimes times are sent as zero - ignore them.
9509          */
9510
9511         /* Ensure we have a valid stat struct for the source. */
9512         status = vfs_stat_fsp(fsp);
9513         if (!NT_STATUS_IS_OK(status)) {
9514                 reply_nterror(req, status);
9515                 goto out;
9516         }
9517
9518         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9519                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9520                 goto out;
9521         }
9522
9523         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9524         if (!NT_STATUS_IS_OK(status)) {
9525                 reply_nterror(req, status);
9526                 goto out;
9527         }
9528
9529         if (fsp->fsp_flags.modified) {
9530                 trigger_write_time_update_immediate(fsp);
9531         }
9532
9533         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9534                " createtime=%u\n",
9535                 fsp_fnum_dbg(fsp),
9536                 (unsigned int)ft.atime.tv_sec,
9537                 (unsigned int)ft.mtime.tv_sec,
9538                 (unsigned int)ft.create_time.tv_sec
9539                 ));
9540  out:
9541         END_PROFILE(SMBsetattrE);
9542         return;
9543 }
9544
9545
9546 /* Back from the dead for OS/2..... JRA. */
9547
9548 /****************************************************************************
9549  Reply to a SMBwritebmpx (write block multiplex primary) request.
9550  Always reply with an error, if someone has a platform really needs this,
9551  please contact vl@samba.org
9552 ****************************************************************************/
9553
9554 void reply_writebmpx(struct smb_request *req)
9555 {
9556         START_PROFILE(SMBwriteBmpx);
9557         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9558         END_PROFILE(SMBwriteBmpx);
9559         return;
9560 }
9561
9562 /****************************************************************************
9563  Reply to a SMBwritebs (write block multiplex secondary) request.
9564  Always reply with an error, if someone has a platform really needs this,
9565  please contact vl@samba.org
9566 ****************************************************************************/
9567
9568 void reply_writebs(struct smb_request *req)
9569 {
9570         START_PROFILE(SMBwriteBs);
9571         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9572         END_PROFILE(SMBwriteBs);
9573         return;
9574 }
9575
9576 /****************************************************************************
9577  Reply to a SMBgetattrE.
9578 ****************************************************************************/
9579
9580 void reply_getattrE(struct smb_request *req)
9581 {
9582         connection_struct *conn = req->conn;
9583         int mode;
9584         files_struct *fsp;
9585         struct timespec create_ts;
9586         NTSTATUS status;
9587
9588         START_PROFILE(SMBgetattrE);
9589
9590         if (req->wct < 1) {
9591                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9592                 END_PROFILE(SMBgetattrE);
9593                 return;
9594         }
9595
9596         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9597
9598         if(!fsp || (fsp->conn != conn)) {
9599                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9600                 END_PROFILE(SMBgetattrE);
9601                 return;
9602         }
9603
9604         /* Do an fstat on this file */
9605         status = vfs_stat_fsp(fsp);
9606         if (!NT_STATUS_IS_OK(status)) {
9607                 reply_nterror(req, status);
9608                 END_PROFILE(SMBgetattrE);
9609                 return;
9610         }
9611
9612         mode = dos_mode(conn, fsp->fsp_name);
9613
9614         /*
9615          * Convert the times into dos times. Set create
9616          * date to be last modify date as UNIX doesn't save
9617          * this.
9618          */
9619
9620         reply_outbuf(req, 11, 0);
9621
9622         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9623         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9624         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9625                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9626         /* Should we check pending modtime here ? JRA */
9627         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9628                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9629
9630         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9631                 SIVAL(req->outbuf, smb_vwv6, 0);
9632                 SIVAL(req->outbuf, smb_vwv8, 0);
9633         } else {
9634                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9635                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9636                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9637         }
9638         SSVAL(req->outbuf,smb_vwv10, mode);
9639
9640         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9641
9642         END_PROFILE(SMBgetattrE);
9643         return;
9644 }