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