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