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