vfs: remove dirfsp arg from SMB_VFS_CREATE_FILE()
[bbaumbach/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, struct smb_request *req,
3272                           uint32_t dirtype, struct smb_filename *smb_fname)
3273 {
3274         char *fname_dir = NULL;
3275         char *fname_mask = NULL;
3276         int count=0;
3277         NTSTATUS status = NT_STATUS_OK;
3278         struct smb_filename *smb_fname_dir = NULL;
3279         bool has_wild = false;
3280         TALLOC_CTX *ctx = talloc_tos();
3281
3282         /* Split up the directory from the filename/mask. */
3283         status = split_fname_dir_mask(ctx, smb_fname->base_name,
3284                                       &fname_dir, &fname_mask);
3285         if (!NT_STATUS_IS_OK(status)) {
3286                 goto out;
3287         }
3288
3289         if (req != NULL && !req->posix_pathnames) {
3290                 /*
3291                  * Check the wildcard mask *before*
3292                  * unmangling. As mangling is done
3293                  * for names that can't be returned
3294                  * to Windows the unmangled name may
3295                  * contain Windows wildcard characters.
3296                  */
3297                 has_wild = ms_has_wild(fname_mask);
3298         }
3299
3300         /*
3301          * We should only check the mangled cache
3302          * here if unix_convert failed. This means
3303          * that the path in 'mask' doesn't exist
3304          * on the file system and so we need to look
3305          * for a possible mangle. This patch from
3306          * Tine Smukavec <valentin.smukavec@hermes.si>.
3307          */
3308
3309         if (!VALID_STAT(smb_fname->st) &&
3310             mangle_is_mangled(fname_mask, conn->params)) {
3311                 char *new_mask = NULL;
3312                 mangle_lookup_name_from_8_3(ctx, fname_mask,
3313                                             &new_mask, conn->params);
3314                 if (new_mask) {
3315                         TALLOC_FREE(fname_mask);
3316                         fname_mask = new_mask;
3317                 }
3318         }
3319
3320         if (!has_wild) {
3321
3322                 /*
3323                  * Only one file needs to be unlinked. Append the mask back
3324                  * onto the directory.
3325                  */
3326                 TALLOC_FREE(smb_fname->base_name);
3327                 if (ISDOT(fname_dir)) {
3328                         /* Ensure we use canonical names on open. */
3329                         smb_fname->base_name = talloc_asprintf(smb_fname,
3330                                                         "%s",
3331                                                         fname_mask);
3332                 } else {
3333                         smb_fname->base_name = talloc_asprintf(smb_fname,
3334                                                         "%s/%s",
3335                                                         fname_dir,
3336                                                         fname_mask);
3337                 }
3338                 if (!smb_fname->base_name) {
3339                         status = NT_STATUS_NO_MEMORY;
3340                         goto out;
3341                 }
3342                 if (dirtype == 0) {
3343                         dirtype = FILE_ATTRIBUTE_NORMAL;
3344                 }
3345
3346                 status = check_name(conn, smb_fname);
3347                 if (!NT_STATUS_IS_OK(status)) {
3348                         goto out;
3349                 }
3350
3351                 status = do_unlink(conn, req, smb_fname, dirtype);
3352                 if (!NT_STATUS_IS_OK(status)) {
3353                         goto out;
3354                 }
3355
3356                 count++;
3357         } else {
3358                 struct smb_Dir *dir_hnd = NULL;
3359                 long offset = 0;
3360                 const char *dname = NULL;
3361                 char *talloced = NULL;
3362
3363                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3364                         status = NT_STATUS_OBJECT_NAME_INVALID;
3365                         goto out;
3366                 }
3367                 if (dirtype == 0) {
3368                         dirtype = FILE_ATTRIBUTE_NORMAL;
3369                 }
3370
3371                 if (strequal(fname_mask,"????????.???")) {
3372                         TALLOC_FREE(fname_mask);
3373                         fname_mask = talloc_strdup(ctx, "*");
3374                         if (!fname_mask) {
3375                                 status = NT_STATUS_NO_MEMORY;
3376                                 goto out;
3377                         }
3378                 }
3379
3380                 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3381                                         fname_dir,
3382                                         NULL,
3383                                         NULL,
3384                                         smb_fname->twrp,
3385                                         smb_fname->flags);
3386                 if (smb_fname_dir == NULL) {
3387                         status = NT_STATUS_NO_MEMORY;
3388                         goto out;
3389                 }
3390
3391                 status = check_name(conn, smb_fname_dir);
3392                 if (!NT_STATUS_IS_OK(status)) {
3393                         goto out;
3394                 }
3395
3396                 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3397                                   dirtype);
3398                 if (dir_hnd == NULL) {
3399                         status = map_nt_error_from_unix(errno);
3400                         goto out;
3401                 }
3402
3403                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3404                    the pattern matches against the long name, otherwise the short name 
3405                    We don't implement this yet XXXX
3406                 */
3407
3408                 status = NT_STATUS_NO_SUCH_FILE;
3409
3410                 while ((dname = ReadDirName(dir_hnd, &offset,
3411                                             &smb_fname->st, &talloced))) {
3412                         TALLOC_CTX *frame = talloc_stackframe();
3413                         char *p = NULL;
3414                         struct smb_filename *f = NULL;
3415
3416                         if (!is_visible_file(conn,
3417                                         dir_hnd,
3418                                         dname,
3419                                         &smb_fname->st,
3420                                         true)) {
3421                                 TALLOC_FREE(frame);
3422                                 TALLOC_FREE(talloced);
3423                                 continue;
3424                         }
3425
3426                         /* Quick check for "." and ".." */
3427                         if (ISDOT(dname) || ISDOTDOT(dname)) {
3428                                 TALLOC_FREE(frame);
3429                                 TALLOC_FREE(talloced);
3430                                 continue;
3431                         }
3432
3433                         if(!mask_match(dname, fname_mask,
3434                                        conn->case_sensitive)) {
3435                                 TALLOC_FREE(frame);
3436                                 TALLOC_FREE(talloced);
3437                                 continue;
3438                         }
3439
3440                         if (ISDOT(fname_dir)) {
3441                                 /* Ensure we use canonical names on open. */
3442                                 p = talloc_asprintf(smb_fname, "%s", dname);
3443                         } else {
3444                                 p = talloc_asprintf(smb_fname, "%s/%s",
3445                                                     fname_dir, dname);
3446                         }
3447                         if (p == NULL) {
3448                                 TALLOC_FREE(dir_hnd);
3449                                 status = NT_STATUS_NO_MEMORY;
3450                                 TALLOC_FREE(frame);
3451                                 TALLOC_FREE(talloced);
3452                                 goto out;
3453                         }
3454                         f = synthetic_smb_fname(frame,
3455                                                 p,
3456                                                 NULL,
3457                                                 &smb_fname->st,
3458                                                 smb_fname->flags,
3459                                                 smb_fname->twrp);
3460                         if (f == NULL) {
3461                                 TALLOC_FREE(dir_hnd);
3462                                 status = NT_STATUS_NO_MEMORY;
3463                                 TALLOC_FREE(frame);
3464                                 TALLOC_FREE(talloced);
3465                                 goto out;
3466                         }
3467
3468                         status = check_name(conn, f);
3469                         if (!NT_STATUS_IS_OK(status)) {
3470                                 TALLOC_FREE(dir_hnd);
3471                                 TALLOC_FREE(frame);
3472                                 TALLOC_FREE(talloced);
3473                                 goto out;
3474                         }
3475
3476                         status = do_unlink(conn, req, f, dirtype);
3477                         if (!NT_STATUS_IS_OK(status)) {
3478                                 TALLOC_FREE(dir_hnd);
3479                                 TALLOC_FREE(frame);
3480                                 TALLOC_FREE(talloced);
3481                                 goto out;
3482                         }
3483
3484                         count++;
3485                         DBG_DEBUG("successful unlink [%s]\n",
3486                                   smb_fname_str_dbg(f));
3487
3488                         TALLOC_FREE(frame);
3489                         TALLOC_FREE(talloced);
3490                 }
3491                 TALLOC_FREE(dir_hnd);
3492         }
3493
3494         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3495                 status = map_nt_error_from_unix(errno);
3496         }
3497
3498  out:
3499         TALLOC_FREE(smb_fname_dir);
3500         TALLOC_FREE(fname_dir);
3501         TALLOC_FREE(fname_mask);
3502         return status;
3503 }
3504
3505 /****************************************************************************
3506  Reply to a unlink
3507 ****************************************************************************/
3508
3509 void reply_unlink(struct smb_request *req)
3510 {
3511         connection_struct *conn = req->conn;
3512         char *name = NULL;
3513         struct smb_filename *smb_fname = NULL;
3514         uint32_t dirtype;
3515         NTSTATUS status;
3516         uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3517                         ucf_flags_from_smb_request(req);
3518         TALLOC_CTX *ctx = talloc_tos();
3519
3520         START_PROFILE(SMBunlink);
3521
3522         if (req->wct < 1) {
3523                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3524                 goto out;
3525         }
3526
3527         dirtype = SVAL(req->vwv+0, 0);
3528
3529         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3530                                   STR_TERMINATE, &status);
3531         if (!NT_STATUS_IS_OK(status)) {
3532                 reply_nterror(req, status);
3533                 goto out;
3534         }
3535
3536         status = filename_convert(ctx, conn,
3537                                   name,
3538                                   ucf_flags,
3539                                   0,
3540                                   &smb_fname);
3541         if (!NT_STATUS_IS_OK(status)) {
3542                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3543                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3544                                         ERRSRV, ERRbadpath);
3545                         goto out;
3546                 }
3547                 reply_nterror(req, status);
3548                 goto out;
3549         }
3550
3551         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3552
3553         status = unlink_internals(conn, req, dirtype, smb_fname);
3554         if (!NT_STATUS_IS_OK(status)) {
3555                 if (open_was_deferred(req->xconn, req->mid)) {
3556                         /* We have re-scheduled this call. */
3557                         goto out;
3558                 }
3559                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3560                         bool ok = defer_smb1_sharing_violation(req);
3561                         if (ok) {
3562                                 goto out;
3563                         }
3564                 }
3565                 reply_nterror(req, status);
3566                 goto out;
3567         }
3568
3569         reply_outbuf(req, 0, 0);
3570  out:
3571         TALLOC_FREE(smb_fname);
3572         END_PROFILE(SMBunlink);
3573         return;
3574 }
3575
3576 /****************************************************************************
3577  Fail for readbraw.
3578 ****************************************************************************/
3579
3580 static void fail_readraw(void)
3581 {
3582         const char *errstr = talloc_asprintf(talloc_tos(),
3583                         "FAIL ! reply_readbraw: socket write fail (%s)",
3584                         strerror(errno));
3585         if (!errstr) {
3586                 errstr = "";
3587         }
3588         exit_server_cleanly(errstr);
3589 }
3590
3591 /****************************************************************************
3592  Fake (read/write) sendfile. Returns -1 on read or write fail.
3593 ****************************************************************************/
3594
3595 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3596                       off_t startpos, size_t nread)
3597 {
3598         size_t bufsize;
3599         size_t tosend = nread;
3600         char *buf;
3601
3602         if (nread == 0) {
3603                 return 0;
3604         }
3605
3606         bufsize = MIN(nread, 65536);
3607
3608         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3609                 return -1;
3610         }
3611
3612         while (tosend > 0) {
3613                 ssize_t ret;
3614                 size_t cur_read;
3615
3616                 cur_read = MIN(tosend, bufsize);
3617                 ret = read_file(fsp,buf,startpos,cur_read);
3618                 if (ret == -1) {
3619                         SAFE_FREE(buf);
3620                         return -1;
3621                 }
3622
3623                 /* If we had a short read, fill with zeros. */
3624                 if (ret < cur_read) {
3625                         memset(buf + ret, '\0', cur_read - ret);
3626                 }
3627
3628                 ret = write_data(xconn->transport.sock, buf, cur_read);
3629                 if (ret != cur_read) {
3630                         int saved_errno = errno;
3631                         /*
3632                          * Try and give an error message saying what
3633                          * client failed.
3634                          */
3635                         DEBUG(0, ("write_data failed for client %s. "
3636                                   "Error %s\n",
3637                                   smbXsrv_connection_dbg(xconn),
3638                                   strerror(saved_errno)));
3639                         SAFE_FREE(buf);
3640                         errno = saved_errno;
3641                         return -1;
3642                 }
3643                 tosend -= cur_read;
3644                 startpos += cur_read;
3645         }
3646
3647         SAFE_FREE(buf);
3648         return (ssize_t)nread;
3649 }
3650
3651 /****************************************************************************
3652  Deal with the case of sendfile reading less bytes from the file than
3653  requested. Fill with zeros (all we can do). Returns 0 on success
3654 ****************************************************************************/
3655
3656 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3657                             files_struct *fsp,
3658                             ssize_t nread,
3659                             size_t headersize,
3660                             size_t smb_maxcnt)
3661 {
3662 #define SHORT_SEND_BUFSIZE 1024
3663         if (nread < headersize) {
3664                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3665                         "header for file %s (%s). Terminating\n",
3666                         fsp_str_dbg(fsp), strerror(errno)));
3667                 return -1;
3668         }
3669
3670         nread -= headersize;
3671
3672         if (nread < smb_maxcnt) {
3673                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3674                 if (!buf) {
3675                         DEBUG(0,("sendfile_short_send: malloc failed "
3676                                 "for file %s (%s). Terminating\n",
3677                                 fsp_str_dbg(fsp), strerror(errno)));
3678                         return -1;
3679                 }
3680
3681                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3682                         "with zeros !\n", fsp_str_dbg(fsp)));
3683
3684                 while (nread < smb_maxcnt) {
3685                         /*
3686                          * We asked for the real file size and told sendfile
3687                          * to not go beyond the end of the file. But it can
3688                          * happen that in between our fstat call and the
3689                          * sendfile call the file was truncated. This is very
3690                          * bad because we have already announced the larger
3691                          * number of bytes to the client.
3692                          *
3693                          * The best we can do now is to send 0-bytes, just as
3694                          * a read from a hole in a sparse file would do.
3695                          *
3696                          * This should happen rarely enough that I don't care
3697                          * about efficiency here :-)
3698                          */
3699                         size_t to_write;
3700                         ssize_t ret;
3701
3702                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3703                         ret = write_data(xconn->transport.sock, buf, to_write);
3704                         if (ret != to_write) {
3705                                 int saved_errno = errno;
3706                                 /*
3707                                  * Try and give an error message saying what
3708                                  * client failed.
3709                                  */
3710                                 DEBUG(0, ("write_data failed for client %s. "
3711                                           "Error %s\n",
3712                                           smbXsrv_connection_dbg(xconn),
3713                                           strerror(saved_errno)));
3714                                 errno = saved_errno;
3715                                 return -1;
3716                         }
3717                         nread += to_write;
3718                 }
3719                 SAFE_FREE(buf);
3720         }
3721
3722         return 0;
3723 }
3724
3725 /****************************************************************************
3726  Return a readbraw error (4 bytes of zero).
3727 ****************************************************************************/
3728
3729 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3730 {
3731         char header[4];
3732
3733         SIVAL(header,0,0);
3734
3735         smbd_lock_socket(xconn);
3736         if (write_data(xconn->transport.sock,header,4) != 4) {
3737                 int saved_errno = errno;
3738                 /*
3739                  * Try and give an error message saying what
3740                  * client failed.
3741                  */
3742                 DEBUG(0, ("write_data failed for client %s. "
3743                           "Error %s\n",
3744                           smbXsrv_connection_dbg(xconn),
3745                           strerror(saved_errno)));
3746                 errno = saved_errno;
3747
3748                 fail_readraw();
3749         }
3750         smbd_unlock_socket(xconn);
3751 }
3752
3753 /*******************************************************************
3754  Ensure we don't use sendfile if server smb signing is active.
3755 ********************************************************************/
3756
3757 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3758 {
3759         bool sign_active = false;
3760
3761         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3762         if (get_Protocol() < PROTOCOL_NT1) {
3763                 return false;
3764         }
3765         if (signing_state) {
3766                 sign_active = smb_signing_is_active(signing_state);
3767         }
3768         return (lp__use_sendfile(snum) &&
3769                         (get_remote_arch() != RA_WIN95) &&
3770                         !sign_active);
3771 }
3772 /****************************************************************************
3773  Use sendfile in readbraw.
3774 ****************************************************************************/
3775
3776 static void send_file_readbraw(connection_struct *conn,
3777                                struct smb_request *req,
3778                                files_struct *fsp,
3779                                off_t startpos,
3780                                size_t nread,
3781                                ssize_t mincount)
3782 {
3783         struct smbXsrv_connection *xconn = req->xconn;
3784         char *outbuf = NULL;
3785         ssize_t ret=0;
3786
3787         /*
3788          * We can only use sendfile on a non-chained packet 
3789          * but we can use on a non-oplocked file. tridge proved this
3790          * on a train in Germany :-). JRA.
3791          * reply_readbraw has already checked the length.
3792          */
3793
3794         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3795             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3796                 ssize_t sendfile_read = -1;
3797                 char header[4];
3798                 DATA_BLOB header_blob;
3799
3800                 _smb_setlen(header,nread);
3801                 header_blob = data_blob_const(header, 4);
3802
3803                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3804                                                  &header_blob, startpos,
3805                                                  nread);
3806                 if (sendfile_read == -1) {
3807                         /* Returning ENOSYS means no data at all was sent.
3808                          * Do this as a normal read. */
3809                         if (errno == ENOSYS) {
3810                                 goto normal_readbraw;
3811                         }
3812
3813                         /*
3814                          * Special hack for broken Linux with no working sendfile. If we
3815                          * return EINTR we sent the header but not the rest of the data.
3816                          * Fake this up by doing read/write calls.
3817                          */
3818                         if (errno == EINTR) {
3819                                 /* Ensure we don't do this again. */
3820                                 set_use_sendfile(SNUM(conn), False);
3821                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3822
3823                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3824                                         DEBUG(0,("send_file_readbraw: "
3825                                                  "fake_sendfile failed for "
3826                                                  "file %s (%s).\n",
3827                                                  fsp_str_dbg(fsp),
3828                                                  strerror(errno)));
3829                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3830                                 }
3831                                 return;
3832                         }
3833
3834                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3835                                  "file %s (%s). Terminating\n",
3836                                  fsp_str_dbg(fsp), strerror(errno)));
3837                         exit_server_cleanly("send_file_readbraw sendfile failed");
3838                 } else if (sendfile_read == 0) {
3839                         /*
3840                          * Some sendfile implementations return 0 to indicate
3841                          * that there was a short read, but nothing was
3842                          * actually written to the socket.  In this case,
3843                          * fallback to the normal read path so the header gets
3844                          * the correct byte count.
3845                          */
3846                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3847                                   "bytes falling back to the normal read: "
3848                                   "%s\n", fsp_str_dbg(fsp)));
3849                         goto normal_readbraw;
3850                 }
3851
3852                 /* Deal with possible short send. */
3853                 if (sendfile_read != 4+nread) {
3854                         ret = sendfile_short_send(xconn, fsp,
3855                                                   sendfile_read, 4, nread);
3856                         if (ret == -1) {
3857                                 fail_readraw();
3858                         }
3859                 }
3860                 return;
3861         }
3862
3863 normal_readbraw:
3864
3865         outbuf = talloc_array(NULL, char, nread+4);
3866         if (!outbuf) {
3867                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3868                         (unsigned)(nread+4)));
3869                 reply_readbraw_error(xconn);
3870                 return;
3871         }
3872
3873         if (nread > 0) {
3874                 ret = read_file(fsp,outbuf+4,startpos,nread);
3875 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3876                 if (ret < mincount)
3877                         ret = 0;
3878 #else
3879                 if (ret < nread)
3880                         ret = 0;
3881 #endif
3882         }
3883
3884         _smb_setlen(outbuf,ret);
3885         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3886                 int saved_errno = errno;
3887                 /*
3888                  * Try and give an error message saying what
3889                  * client failed.
3890                  */
3891                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3892                           smbXsrv_connection_dbg(xconn),
3893                           strerror(saved_errno)));
3894                 errno = saved_errno;
3895
3896                 fail_readraw();
3897         }
3898
3899         TALLOC_FREE(outbuf);
3900 }
3901
3902 /****************************************************************************
3903  Reply to a readbraw (core+ protocol).
3904 ****************************************************************************/
3905
3906 void reply_readbraw(struct smb_request *req)
3907 {
3908         connection_struct *conn = req->conn;
3909         struct smbXsrv_connection *xconn = req->xconn;
3910         ssize_t maxcount,mincount;
3911         size_t nread = 0;
3912         off_t startpos;
3913         files_struct *fsp;
3914         struct lock_struct lock;
3915         off_t size = 0;
3916         NTSTATUS status;
3917
3918         START_PROFILE(SMBreadbraw);
3919
3920         if (srv_is_signing_active(xconn) || req->encrypted) {
3921                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3922                         "raw reads/writes are disallowed.");
3923         }
3924
3925         if (req->wct < 8) {
3926                 reply_readbraw_error(xconn);
3927                 END_PROFILE(SMBreadbraw);
3928                 return;
3929         }
3930
3931         if (xconn->smb1.echo_handler.trusted_fde) {
3932                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3933                          "'async smb echo handler = yes'\n"));
3934                 reply_readbraw_error(xconn);
3935                 END_PROFILE(SMBreadbraw);
3936                 return;
3937         }
3938
3939         /*
3940          * Special check if an oplock break has been issued
3941          * and the readraw request croses on the wire, we must
3942          * return a zero length response here.
3943          */
3944
3945         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3946
3947         /*
3948          * We have to do a check_fsp by hand here, as
3949          * we must always return 4 zero bytes on error,
3950          * not a NTSTATUS.
3951          */
3952
3953         if (fsp == NULL ||
3954             conn == NULL ||
3955             conn != fsp->conn ||
3956             req->vuid != fsp->vuid ||
3957             fsp->fsp_flags.is_directory ||
3958             fsp->fh->fd == -1)
3959         {
3960                 /*
3961                  * fsp could be NULL here so use the value from the packet. JRA.
3962                  */
3963                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3964                         "- cache prime?\n",
3965                         (int)SVAL(req->vwv+0, 0)));
3966                 reply_readbraw_error(xconn);
3967                 END_PROFILE(SMBreadbraw);
3968                 return;
3969         }
3970
3971         /* Do a "by hand" version of CHECK_READ. */
3972         if (!(fsp->fsp_flags.can_read ||
3973                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3974                                 (fsp->access_mask & FILE_EXECUTE)))) {
3975                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3976                                 (int)SVAL(req->vwv+0, 0)));
3977                 reply_readbraw_error(xconn);
3978                 END_PROFILE(SMBreadbraw);
3979                 return;
3980         }
3981
3982         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3983         if(req->wct == 10) {
3984                 /*
3985                  * This is a large offset (64 bit) read.
3986                  */
3987
3988                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3989
3990                 if(startpos < 0) {
3991                         DEBUG(0,("reply_readbraw: negative 64 bit "
3992                                 "readraw offset (%.0f) !\n",
3993                                 (double)startpos ));
3994                         reply_readbraw_error(xconn);
3995                         END_PROFILE(SMBreadbraw);
3996                         return;
3997                 }
3998         }
3999
4000         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4001         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4002
4003         /* ensure we don't overrun the packet size */
4004         maxcount = MIN(65535,maxcount);
4005
4006         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4007             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4008             &lock);
4009
4010         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4011                 reply_readbraw_error(xconn);
4012                 END_PROFILE(SMBreadbraw);
4013                 return;
4014         }
4015
4016         status = vfs_stat_fsp(fsp);
4017         if (NT_STATUS_IS_OK(status)) {
4018                 size = fsp->fsp_name->st.st_ex_size;
4019         }
4020
4021         if (startpos >= size) {
4022                 nread = 0;
4023         } else {
4024                 nread = MIN(maxcount,(size - startpos));
4025         }
4026
4027 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4028         if (nread < mincount)
4029                 nread = 0;
4030 #endif
4031
4032         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4033                 "min=%lu nread=%lu\n",
4034                 fsp_fnum_dbg(fsp), (double)startpos,
4035                 (unsigned long)maxcount,
4036                 (unsigned long)mincount,
4037                 (unsigned long)nread ) );
4038
4039         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4040
4041         DEBUG(5,("reply_readbraw finished\n"));
4042
4043         END_PROFILE(SMBreadbraw);
4044         return;
4045 }
4046
4047 #undef DBGC_CLASS
4048 #define DBGC_CLASS DBGC_LOCKING
4049
4050 /****************************************************************************
4051  Reply to a lockread (core+ protocol).
4052 ****************************************************************************/
4053
4054 static void reply_lockread_locked(struct tevent_req *subreq);
4055
4056 void reply_lockread(struct smb_request *req)
4057 {
4058         struct tevent_req *subreq = NULL;
4059         connection_struct *conn = req->conn;
4060         files_struct *fsp;
4061         struct smbd_lock_element *lck = NULL;
4062
4063         START_PROFILE(SMBlockread);
4064
4065         if (req->wct < 5) {
4066                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4067                 END_PROFILE(SMBlockread);
4068                 return;
4069         }
4070
4071         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4072
4073         if (!check_fsp(conn, req, fsp)) {
4074                 END_PROFILE(SMBlockread);
4075                 return;
4076         }
4077
4078         if (!CHECK_READ(fsp,req)) {
4079                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4080                 END_PROFILE(SMBlockread);
4081                 return;
4082         }
4083
4084         lck = talloc(req, struct smbd_lock_element);
4085         if (lck == NULL) {
4086                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4087                 END_PROFILE(SMBlockread);
4088                 return;
4089         }
4090
4091         /*
4092          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4093          * protocol request that predates the read/write lock concept. 
4094          * Thus instead of asking for a read lock here we need to ask
4095          * for a write lock. JRA.
4096          * Note that the requested lock size is unaffected by max_send.
4097          */
4098
4099         *lck = (struct smbd_lock_element) {
4100                 .req_guid = smbd_request_guid(req, 0),
4101                 .smblctx = req->smbpid,
4102                 .brltype = WRITE_LOCK,
4103                 .count = SVAL(req->vwv+1, 0),
4104                 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4105         };
4106
4107         subreq = smbd_smb1_do_locks_send(
4108                 fsp,
4109                 req->sconn->ev_ctx,
4110                 &req,
4111                 fsp,
4112                 0,
4113                 false,          /* large_offset */
4114                 WINDOWS_LOCK,
4115                 1,
4116                 lck);
4117         if (subreq == NULL) {
4118                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4119                 END_PROFILE(SMBlockread);
4120                 return;
4121         }
4122         tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4123         END_PROFILE(SMBlockread);
4124 }
4125
4126 static void reply_lockread_locked(struct tevent_req *subreq)
4127 {
4128         struct smb_request *req = NULL;
4129         ssize_t nread = -1;
4130         char *data = NULL;
4131         NTSTATUS status;
4132         bool ok;
4133         off_t startpos;
4134         size_t numtoread, maxtoread;
4135         struct files_struct *fsp = NULL;
4136         char *p = NULL;
4137
4138         START_PROFILE(SMBlockread);
4139
4140         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4141         SMB_ASSERT(ok);
4142
4143         status = smbd_smb1_do_locks_recv(subreq);
4144         TALLOC_FREE(subreq);
4145
4146         if (!NT_STATUS_IS_OK(status)) {
4147                 reply_nterror(req, status);
4148                 goto send;
4149         }
4150
4151         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4152         if (fsp == NULL) {
4153                 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4154                 goto send;
4155         }
4156
4157         numtoread = SVAL(req->vwv+1, 0);
4158         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4159
4160         /*
4161          * However the requested READ size IS affected by max_send. Insanity.... JRA.
4162          */
4163         maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4164
4165         if (numtoread > maxtoread) {
4166                 DBG_WARNING("requested read size (%zu) is greater than "
4167                             "maximum allowed (%zu/%d). "
4168                             "Returning short read of maximum allowed for "
4169                             "compatibility with Windows 2000.\n",
4170                             numtoread,
4171                             maxtoread,
4172                             req->xconn->smb1.sessions.max_send);
4173                 numtoread = maxtoread;
4174         }
4175
4176         reply_outbuf(req, 5, numtoread + 3);
4177
4178         data = smb_buf(req->outbuf) + 3;
4179
4180         nread = read_file(fsp,data,startpos,numtoread);
4181
4182         if (nread < 0) {
4183                 reply_nterror(req, map_nt_error_from_unix(errno));
4184                 goto send;
4185         }
4186
4187         srv_set_message((char *)req->outbuf, 5, nread+3, False);
4188
4189         SSVAL(req->outbuf,smb_vwv0,nread);
4190         SSVAL(req->outbuf,smb_vwv5,nread+3);
4191         p = smb_buf(req->outbuf);
4192         SCVAL(p,0,0); /* pad byte. */
4193         SSVAL(p,1,nread);
4194
4195         DEBUG(3,("lockread %s num=%d nread=%d\n",
4196                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4197
4198 send:
4199         ok = srv_send_smb(req->xconn,
4200                           (char *)req->outbuf,
4201                           true,
4202                           req->seqnum+1,
4203                           IS_CONN_ENCRYPTED(req->conn),
4204                           NULL);
4205         if (!ok) {
4206                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4207         }
4208         TALLOC_FREE(req);
4209         END_PROFILE(SMBlockread);
4210         return;
4211 }
4212
4213 #undef DBGC_CLASS
4214 #define DBGC_CLASS DBGC_ALL
4215
4216 /****************************************************************************
4217  Reply to a read.
4218 ****************************************************************************/
4219
4220 void reply_read(struct smb_request *req)
4221 {
4222         connection_struct *conn = req->conn;
4223         size_t numtoread;
4224         size_t maxtoread;
4225         ssize_t nread = 0;
4226         char *data;
4227         off_t startpos;
4228         files_struct *fsp;
4229         struct lock_struct lock;
4230         struct smbXsrv_connection *xconn = req->xconn;
4231
4232         START_PROFILE(SMBread);
4233
4234         if (req->wct < 3) {
4235                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4236                 END_PROFILE(SMBread);
4237                 return;
4238         }
4239
4240         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4241
4242         if (!check_fsp(conn, req, fsp)) {
4243                 END_PROFILE(SMBread);
4244                 return;
4245         }
4246
4247         if (!CHECK_READ(fsp,req)) {
4248                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4249                 END_PROFILE(SMBread);
4250                 return;
4251         }
4252
4253         numtoread = SVAL(req->vwv+1, 0);
4254         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4255
4256         /*
4257          * The requested read size cannot be greater than max_send. JRA.
4258          */
4259         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4260
4261         if (numtoread > maxtoread) {
4262                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4263 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4264                         (unsigned int)numtoread, (unsigned int)maxtoread,
4265                         (unsigned int)xconn->smb1.sessions.max_send));
4266                 numtoread = maxtoread;
4267         }
4268
4269         reply_outbuf(req, 5, numtoread+3);
4270
4271         data = smb_buf(req->outbuf) + 3;
4272
4273         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4274             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4275             &lock);
4276
4277         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4278                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4279                 END_PROFILE(SMBread);
4280                 return;
4281         }
4282
4283         if (numtoread > 0)
4284                 nread = read_file(fsp,data,startpos,numtoread);
4285
4286         if (nread < 0) {
4287                 reply_nterror(req, map_nt_error_from_unix(errno));
4288                 goto out;
4289         }
4290
4291         srv_set_message((char *)req->outbuf, 5, nread+3, False);
4292
4293         SSVAL(req->outbuf,smb_vwv0,nread);
4294         SSVAL(req->outbuf,smb_vwv5,nread+3);
4295         SCVAL(smb_buf(req->outbuf),0,1);
4296         SSVAL(smb_buf(req->outbuf),1,nread);
4297
4298         DEBUG(3, ("read %s num=%d nread=%d\n",
4299                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4300
4301 out:
4302         END_PROFILE(SMBread);
4303         return;
4304 }
4305
4306 /****************************************************************************
4307  Setup readX header.
4308 ****************************************************************************/
4309
4310 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4311 {
4312         size_t outsize;
4313
4314         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4315                                   False);
4316
4317         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4318
4319         SCVAL(outbuf,smb_vwv0,0xFF);
4320         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4321         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4322         SSVAL(outbuf,smb_vwv6,
4323               (smb_wct - 4)     /* offset from smb header to wct */
4324               + 1               /* the wct field */
4325               + 12 * sizeof(uint16_t) /* vwv */
4326               + 2               /* the buflen field */
4327               + 1);             /* padding byte */
4328         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4329         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4330         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4331         _smb_setlen_large(outbuf,
4332                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4333         return outsize;
4334 }
4335
4336 /****************************************************************************
4337  Reply to a read and X - possibly using sendfile.
4338 ****************************************************************************/
4339
4340 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4341                             files_struct *fsp, off_t startpos,
4342                             size_t smb_maxcnt)
4343 {
4344         struct smbXsrv_connection *xconn = req->xconn;
4345         ssize_t nread = -1;
4346         struct lock_struct lock;
4347         int saved_errno = 0;
4348         NTSTATUS status;
4349
4350         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4351             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4352             &lock);
4353
4354         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4355                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4356                 return;
4357         }
4358
4359         /*
4360          * We can only use sendfile on a non-chained packet
4361          * but we can use on a non-oplocked file. tridge proved this
4362          * on a train in Germany :-). JRA.
4363          */
4364
4365         if (!req_is_in_chain(req) &&
4366             !req->encrypted &&
4367             (fsp->base_fsp == NULL) &&
4368             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4369                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4370                 DATA_BLOB header;
4371
4372                 status = vfs_stat_fsp(fsp);
4373                 if (!NT_STATUS_IS_OK(status)) {
4374                         reply_nterror(req, status);
4375                         goto out;
4376                 }
4377
4378                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4379                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4380                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4381                         /*
4382                          * We already know that we would do a short read, so don't
4383                          * try the sendfile() path.
4384                          */
4385                         goto nosendfile_read;
4386                 }
4387
4388                 /*
4389                  * Set up the packet header before send. We
4390                  * assume here the sendfile will work (get the
4391                  * correct amount of data).
4392                  */
4393
4394                 header = data_blob_const(headerbuf, sizeof(headerbuf));
4395
4396                 construct_reply_common_req(req, (char *)headerbuf);
4397                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4398
4399                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4400                                          startpos, smb_maxcnt);
4401                 if (nread == -1) {
4402                         saved_errno = errno;
4403
4404                         /* Returning ENOSYS means no data at all was sent.
4405                            Do this as a normal read. */
4406                         if (errno == ENOSYS) {
4407                                 goto normal_read;
4408                         }
4409
4410                         /*
4411                          * Special hack for broken Linux with no working sendfile. If we
4412                          * return EINTR we sent the header but not the rest of the data.
4413                          * Fake this up by doing read/write calls.
4414                          */
4415
4416                         if (errno == EINTR) {
4417                                 /* Ensure we don't do this again. */
4418                                 set_use_sendfile(SNUM(conn), False);
4419                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4420                                 nread = fake_sendfile(xconn, fsp, startpos,
4421                                                       smb_maxcnt);
4422                                 if (nread == -1) {
4423                                         saved_errno = errno;
4424                                         DEBUG(0,("send_file_readX: "
4425                                                  "fake_sendfile failed for "
4426                                                  "file %s (%s) for client %s. "
4427                                                  "Terminating\n",
4428                                                  fsp_str_dbg(fsp),
4429                                                  smbXsrv_connection_dbg(xconn),
4430                                                  strerror(saved_errno)));
4431                                         errno = saved_errno;
4432                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4433                                 }
4434                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4435                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4436                                 /* No outbuf here means successful sendfile. */
4437                                 goto out;
4438                         }
4439
4440                         DEBUG(0,("send_file_readX: sendfile failed for file "
4441                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4442                                  strerror(errno)));
4443                         exit_server_cleanly("send_file_readX sendfile failed");
4444                 } else if (nread == 0) {
4445                         /*
4446                          * Some sendfile implementations return 0 to indicate
4447                          * that there was a short read, but nothing was
4448                          * actually written to the socket.  In this case,
4449                          * fallback to the normal read path so the header gets
4450                          * the correct byte count.
4451                          */
4452                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4453                                   "falling back to the normal read: %s\n",
4454                                   fsp_str_dbg(fsp)));
4455                         goto normal_read;
4456                 }
4457
4458                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4459                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4460
4461                 /* Deal with possible short send. */
4462                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4463                         ssize_t ret;
4464
4465                         ret = sendfile_short_send(xconn, fsp, nread,
4466                                                   sizeof(headerbuf), smb_maxcnt);
4467                         if (ret == -1) {
4468                                 const char *r;
4469                                 r = "send_file_readX: sendfile_short_send failed";
4470                                 DEBUG(0,("%s for file %s (%s).\n",
4471                                          r, fsp_str_dbg(fsp), strerror(errno)));
4472                                 exit_server_cleanly(r);
4473                         }
4474                 }
4475                 /* No outbuf here means successful sendfile. */
4476                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4477                 SMB_PERFCOUNT_END(&req->pcd);
4478                 goto out;
4479         }
4480
4481 normal_read:
4482
4483         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4484                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4485                 ssize_t ret;
4486
4487                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4488                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4489                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4490                         /*
4491                          * We already know that we would do a short
4492                          * read, so don't try the sendfile() path.
4493                          */
4494                         goto nosendfile_read;
4495                 }
4496
4497                 construct_reply_common_req(req, (char *)headerbuf);
4498                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4499
4500                 /* Send out the header. */
4501                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4502                                  sizeof(headerbuf));
4503                 if (ret != sizeof(headerbuf)) {
4504                         saved_errno = errno;
4505                         /*
4506                          * Try and give an error message saying what
4507                          * client failed.
4508                          */
4509                         DEBUG(0,("send_file_readX: write_data failed for file "
4510                                  "%s (%s) for client %s. Terminating\n",
4511                                  fsp_str_dbg(fsp),
4512                                  smbXsrv_connection_dbg(xconn),
4513                                  strerror(saved_errno)));
4514                         errno = saved_errno;
4515                         exit_server_cleanly("send_file_readX sendfile failed");
4516                 }
4517                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4518                 if (nread == -1) {
4519                         saved_errno = errno;
4520                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4521                                  "%s (%s) for client %s. Terminating\n",
4522                                  fsp_str_dbg(fsp),
4523                                  smbXsrv_connection_dbg(xconn),
4524                                  strerror(saved_errno)));
4525                         errno = saved_errno;
4526                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4527                 }
4528                 goto out;
4529         }
4530
4531 nosendfile_read:
4532
4533         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4534         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4535         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4536
4537         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4538                           startpos, smb_maxcnt);
4539         saved_errno = errno;
4540
4541         if (nread < 0) {
4542                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4543                 return;
4544         }
4545
4546         setup_readX_header((char *)req->outbuf, nread);
4547
4548         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4549                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4550         return;
4551
4552 out:
4553         TALLOC_FREE(req->outbuf);
4554         return;
4555 }
4556
4557 /****************************************************************************
4558  Work out how much space we have for a read return.
4559 ****************************************************************************/
4560
4561 static size_t calc_max_read_pdu(const struct smb_request *req)
4562 {
4563         struct smbXsrv_connection *xconn = req->xconn;
4564
4565         if (xconn->protocol < PROTOCOL_NT1) {
4566                 return xconn->smb1.sessions.max_send;
4567         }
4568
4569         if (!lp_large_readwrite()) {
4570                 return xconn->smb1.sessions.max_send;
4571         }
4572
4573         if (req_is_in_chain(req)) {
4574                 return xconn->smb1.sessions.max_send;
4575         }
4576
4577         if (req->encrypted) {
4578                 /*
4579                  * Don't take encrypted traffic up to the
4580                  * limit. There are padding considerations
4581                  * that make that tricky.
4582                  */
4583                 return xconn->smb1.sessions.max_send;
4584         }
4585
4586         if (srv_is_signing_active(xconn)) {
4587                 return 0x1FFFF;
4588         }
4589
4590         if (!lp_unix_extensions()) {
4591                 return 0x1FFFF;
4592         }
4593
4594         /*
4595          * We can do ultra-large POSIX reads.
4596          */
4597         return 0xFFFFFF;
4598 }
4599
4600 /****************************************************************************
4601  Calculate how big a read can be. Copes with all clients. It's always
4602  safe to return a short read - Windows does this.
4603 ****************************************************************************/
4604
4605 static size_t calc_read_size(const struct smb_request *req,
4606                              size_t upper_size,
4607                              size_t lower_size)
4608 {
4609         struct smbXsrv_connection *xconn = req->xconn;
4610         size_t max_pdu = calc_max_read_pdu(req);
4611         size_t total_size = 0;
4612         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4613         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4614
4615         /*
4616          * Windows explicitly ignores upper size of 0xFFFF.
4617          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4618          * We must do the same as these will never fit even in
4619          * an extended size NetBIOS packet.
4620          */
4621         if (upper_size == 0xFFFF) {
4622                 upper_size = 0;
4623         }
4624
4625         if (xconn->protocol < PROTOCOL_NT1) {
4626                 upper_size = 0;
4627         }
4628
4629         total_size = ((upper_size<<16) | lower_size);
4630
4631         /*
4632          * LARGE_READX test shows it's always safe to return
4633          * a short read. Windows does so.
4634          */
4635         return MIN(total_size, max_len);
4636 }
4637
4638 /****************************************************************************
4639  Reply to a read and X.
4640 ****************************************************************************/
4641
4642 void reply_read_and_X(struct smb_request *req)
4643 {
4644         connection_struct *conn = req->conn;
4645         files_struct *fsp;
4646         off_t startpos;
4647         size_t smb_maxcnt;
4648         size_t upper_size;
4649         bool big_readX = False;
4650 #if 0
4651         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4652 #endif
4653
4654         START_PROFILE(SMBreadX);
4655
4656         if ((req->wct != 10) && (req->wct != 12)) {
4657                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4658                 return;
4659         }
4660
4661         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4662         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4663         smb_maxcnt = SVAL(req->vwv+5, 0);
4664
4665         /* If it's an IPC, pass off the pipe handler. */
4666         if (IS_IPC(conn)) {
4667                 reply_pipe_read_and_X(req);
4668                 END_PROFILE(SMBreadX);
4669                 return;
4670         }
4671
4672         if (!check_fsp(conn, req, fsp)) {
4673                 END_PROFILE(SMBreadX);
4674                 return;
4675         }
4676
4677         if (!CHECK_READ(fsp,req)) {
4678                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4679                 END_PROFILE(SMBreadX);
4680                 return;
4681         }
4682
4683         upper_size = SVAL(req->vwv+7, 0);
4684         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4685         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4686                 /*
4687                  * This is a heuristic to avoid keeping large
4688                  * outgoing buffers around over long-lived aio
4689                  * requests.
4690                  */
4691                 big_readX = True;
4692         }
4693
4694         if (req->wct == 12) {
4695                 /*
4696                  * This is a large offset (64 bit) read.
4697                  */
4698                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4699
4700         }
4701
4702         if (!big_readX) {
4703                 NTSTATUS status = schedule_aio_read_and_X(conn,
4704                                         req,
4705                                         fsp,
4706                                         startpos,
4707                                         smb_maxcnt);
4708                 if (NT_STATUS_IS_OK(status)) {
4709                         /* Read scheduled - we're done. */
4710                         goto out;
4711                 }
4712                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4713                         /* Real error - report to client. */
4714                         END_PROFILE(SMBreadX);
4715                         reply_nterror(req, status);
4716                         return;
4717                 }
4718                 /* NT_STATUS_RETRY - fall back to sync read. */
4719         }
4720
4721         smbd_lock_socket(req->xconn);
4722         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4723         smbd_unlock_socket(req->xconn);
4724
4725  out:
4726         END_PROFILE(SMBreadX);
4727         return;
4728 }
4729
4730 /****************************************************************************
4731  Error replies to writebraw must have smb_wct == 1. Fix this up.
4732 ****************************************************************************/
4733
4734 void error_to_writebrawerr(struct smb_request *req)
4735 {
4736         uint8_t *old_outbuf = req->outbuf;
4737
4738         reply_outbuf(req, 1, 0);
4739
4740         memcpy(req->outbuf, old_outbuf, smb_size);
4741         TALLOC_FREE(old_outbuf);
4742 }
4743
4744 /****************************************************************************
4745  Read 4 bytes of a smb packet and return the smb length of the packet.
4746  Store the result in the buffer. This version of the function will
4747  never return a session keepalive (length of zero).
4748  Timeout is in milliseconds.
4749 ****************************************************************************/
4750
4751 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4752                                 size_t *len)
4753 {
4754         uint8_t msgtype = NBSSkeepalive;
4755
4756         while (msgtype == NBSSkeepalive) {
4757                 NTSTATUS status;
4758
4759                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4760                                                           len);
4761                 if (!NT_STATUS_IS_OK(status)) {
4762                         char addr[INET6_ADDRSTRLEN];
4763                         /* Try and give an error message
4764                          * saying what client failed. */
4765                         DEBUG(0, ("read_smb_length_return_keepalive failed for "
4766                                   "client %s read error = %s.\n",
4767                                   get_peer_addr(fd,addr,sizeof(addr)),
4768                                   nt_errstr(status)));
4769                         return status;
4770                 }
4771
4772                 msgtype = CVAL(inbuf, 0);
4773         }
4774
4775         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4776                   (unsigned long)len));
4777
4778         return NT_STATUS_OK;
4779 }
4780
4781 /****************************************************************************
4782  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4783 ****************************************************************************/
4784
4785 void reply_writebraw(struct smb_request *req)
4786 {
4787         connection_struct *conn = req->conn;
4788         struct smbXsrv_connection *xconn = req->xconn;
4789         char *buf = NULL;
4790         ssize_t nwritten=0;
4791         ssize_t total_written=0;
4792         size_t numtowrite=0;
4793         size_t tcount;
4794         off_t startpos;
4795         const char *data=NULL;
4796         bool write_through;
4797         files_struct *fsp;
4798         struct lock_struct lock;
4799         NTSTATUS status;
4800
4801         START_PROFILE(SMBwritebraw);
4802
4803         /*
4804          * If we ever reply with an error, it must have the SMB command
4805          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4806          * we're finished.
4807          */
4808         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4809
4810         if (srv_is_signing_active(xconn)) {
4811                 END_PROFILE(SMBwritebraw);
4812                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4813                                 "raw reads/writes are disallowed.");
4814         }
4815
4816         if (req->wct < 12) {
4817                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818                 error_to_writebrawerr(req);
4819                 END_PROFILE(SMBwritebraw);
4820                 return;
4821         }
4822
4823         if (xconn->smb1.echo_handler.trusted_fde) {
4824                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4825                          "'async smb echo handler = yes'\n"));
4826                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4827                 error_to_writebrawerr(req);
4828                 END_PROFILE(SMBwritebraw);
4829                 return;
4830         }
4831
4832         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4833         if (!check_fsp(conn, req, fsp)) {
4834                 error_to_writebrawerr(req);
4835                 END_PROFILE(SMBwritebraw);
4836                 return;
4837         }
4838
4839         if (!CHECK_WRITE(fsp)) {
4840                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4841                 error_to_writebrawerr(req);
4842                 END_PROFILE(SMBwritebraw);
4843                 return;
4844         }
4845
4846         tcount = IVAL(req->vwv+1, 0);
4847         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4848         write_through = BITSETW(req->vwv+7,0);
4849
4850         /* We have to deal with slightly different formats depending
4851                 on whether we are using the core+ or lanman1.0 protocol */
4852
4853         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4854                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4855                 data = smb_buf_const(req->inbuf);
4856         } else {
4857                 numtowrite = SVAL(req->vwv+10, 0);
4858                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4859         }
4860
4861         /* Ensure we don't write bytes past the end of this packet. */
4862         /*
4863          * This already protects us against CVE-2017-12163.
4864          */
4865         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4866                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4867                 error_to_writebrawerr(req);
4868                 END_PROFILE(SMBwritebraw);
4869                 return;
4870         }
4871
4872         if (!fsp->print_file) {
4873                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4874                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4875                     &lock);
4876
4877                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4878                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4879                         error_to_writebrawerr(req);
4880                         END_PROFILE(SMBwritebraw);
4881                         return;
4882                 }
4883         }
4884
4885         if (numtowrite>0) {
4886                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4887         }
4888
4889         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4890                         "wrote=%d sync=%d\n",
4891                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4892                 (int)nwritten, (int)write_through));
4893
4894         if (nwritten < (ssize_t)numtowrite)  {
4895                 reply_nterror(req, NT_STATUS_DISK_FULL);
4896                 error_to_writebrawerr(req);
4897                 goto out;
4898         }
4899
4900         total_written = nwritten;
4901
4902         /* Allocate a buffer of 64k + length. */
4903         buf = talloc_array(NULL, char, 65540);
4904         if (!buf) {
4905                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4906                 error_to_writebrawerr(req);
4907                 goto out;
4908         }
4909
4910         /* Return a SMBwritebraw message to the redirector to tell
4911          * it to send more bytes */
4912
4913         memcpy(buf, req->inbuf, smb_size);
4914         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4915         SCVAL(buf,smb_com,SMBwritebraw);
4916         SSVALS(buf,smb_vwv0,0xFFFF);
4917         show_msg(buf);
4918         if (!srv_send_smb(req->xconn,
4919                           buf,
4920                           false, 0, /* no signing */
4921                           IS_CONN_ENCRYPTED(conn),
4922                           &req->pcd)) {
4923                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4924                         "failed.");
4925         }
4926
4927         /* Now read the raw data into the buffer and write it */
4928         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4929                                  &numtowrite);
4930         if (!NT_STATUS_IS_OK(status)) {
4931                 exit_server_cleanly("secondary writebraw failed");
4932         }
4933
4934         /* Set up outbuf to return the correct size */
4935         reply_outbuf(req, 1, 0);
4936
4937         if (numtowrite != 0) {
4938
4939                 if (numtowrite > 0xFFFF) {
4940                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4941                                 "raw requested (%u). Terminating\n",
4942                                 (unsigned int)numtowrite ));
4943                         exit_server_cleanly("secondary writebraw failed");
4944                 }
4945
4946                 if (tcount > nwritten+numtowrite) {
4947                         DEBUG(3,("reply_writebraw: Client overestimated the "
4948                                 "write %d %d %d\n",
4949                                 (int)tcount,(int)nwritten,(int)numtowrite));
4950                 }
4951
4952                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4953                                             numtowrite);
4954
4955                 if (!NT_STATUS_IS_OK(status)) {
4956                         /* Try and give an error message
4957                          * saying what client failed. */
4958                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4959                                   "raw read failed (%s) for client %s. "
4960                                   "Terminating\n", nt_errstr(status),
4961                                   smbXsrv_connection_dbg(xconn)));
4962                         exit_server_cleanly("secondary writebraw failed");
4963                 }
4964
4965                 /*
4966                  * We are not vulnerable to CVE-2017-12163
4967                  * here as we are guaranteed to have numtowrite
4968                  * bytes available - we just read from the client.
4969                  */
4970                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4971                 if (nwritten == -1) {
4972                         TALLOC_FREE(buf);
4973                         reply_nterror(req, map_nt_error_from_unix(errno));
4974                         error_to_writebrawerr(req);
4975                         goto out;
4976                 }
4977
4978                 if (nwritten < (ssize_t)numtowrite) {
4979                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4980                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4981                 }
4982
4983                 if (nwritten > 0) {
4984                         total_written += nwritten;
4985                 }
4986         }
4987
4988         TALLOC_FREE(buf);
4989         SSVAL(req->outbuf,smb_vwv0,total_written);
4990
4991         status = sync_file(conn, fsp, write_through);
4992         if (!NT_STATUS_IS_OK(status)) {
4993                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4994                          fsp_str_dbg(fsp), nt_errstr(status)));
4995                 reply_nterror(req, status);
4996                 error_to_writebrawerr(req);
4997                 goto out;
4998         }
4999
5000         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5001                 "wrote=%d\n",
5002                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5003                 (int)total_written));
5004
5005         /* We won't return a status if write through is not selected - this
5006          * follows what WfWg does */
5007         END_PROFILE(SMBwritebraw);
5008
5009         if (!write_through && total_written==tcount) {
5010
5011 #if RABBIT_PELLET_FIX
5012                 /*
5013                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5014                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5015                  * JRA.
5016                  */
5017                 if (!send_keepalive(xconn->transport.sock)) {
5018                         exit_server_cleanly("reply_writebraw: send of "
5019                                 "keepalive failed");
5020                 }
5021 #endif
5022                 TALLOC_FREE(req->outbuf);
5023         }
5024         return;
5025
5026 out:
5027         END_PROFILE(SMBwritebraw);
5028         return;
5029 }
5030
5031 #undef DBGC_CLASS
5032 #define DBGC_CLASS DBGC_LOCKING
5033
5034 /****************************************************************************
5035  Reply to a writeunlock (core+).
5036 ****************************************************************************/
5037
5038 void reply_writeunlock(struct smb_request *req)
5039 {
5040         connection_struct *conn = req->conn;
5041         ssize_t nwritten = -1;
5042         size_t numtowrite;
5043         size_t remaining;
5044         off_t startpos;
5045         const char *data;
5046         NTSTATUS status = NT_STATUS_OK;
5047         files_struct *fsp;
5048         struct lock_struct lock;
5049         int saved_errno = 0;
5050
5051         START_PROFILE(SMBwriteunlock);
5052
5053         if (req->wct < 5) {
5054                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5055                 END_PROFILE(SMBwriteunlock);
5056                 return;
5057         }
5058
5059         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5060
5061         if (!check_fsp(conn, req, fsp)) {
5062                 END_PROFILE(SMBwriteunlock);
5063                 return;
5064         }
5065
5066         if (!CHECK_WRITE(fsp)) {
5067                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5068                 END_PROFILE(SMBwriteunlock);
5069                 return;
5070         }
5071
5072         numtowrite = SVAL(req->vwv+1, 0);
5073         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5074         data = (const char *)req->buf + 3;
5075
5076         /*
5077          * Ensure client isn't asking us to write more than
5078          * they sent. CVE-2017-12163.
5079          */
5080         remaining = smbreq_bufrem(req, data);
5081         if (numtowrite > remaining) {
5082                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5083                 END_PROFILE(SMBwriteunlock);
5084                 return;
5085         }
5086
5087         if (!fsp->print_file && numtowrite > 0) {
5088                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5089                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5090                     &lock);
5091
5092                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5093                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5094                         END_PROFILE(SMBwriteunlock);
5095                         return;
5096                 }
5097         }
5098
5099         /* The special X/Open SMB protocol handling of
5100            zero length writes is *NOT* done for
5101            this call */
5102         if(numtowrite == 0) {
5103                 nwritten = 0;
5104         } else {
5105                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5106                 saved_errno = errno;
5107         }
5108
5109         status = sync_file(conn, fsp, False /* write through */);
5110         if (!NT_STATUS_IS_OK(status)) {
5111                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5112                          fsp_str_dbg(fsp), nt_errstr(status)));
5113                 reply_nterror(req, status);
5114                 goto out;
5115         }
5116
5117         if(nwritten < 0) {
5118                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5119                 goto out;
5120         }
5121
5122         if((nwritten < numtowrite) && (numtowrite != 0)) {
5123                 reply_nterror(req, NT_STATUS_DISK_FULL);
5124                 goto out;
5125         }
5126
5127         if (numtowrite && !fsp->print_file) {
5128                 struct smbd_lock_element l = {
5129                         .req_guid = smbd_request_guid(req, 0),
5130                         .smblctx = req->smbpid,
5131                         .brltype = UNLOCK_LOCK,
5132                         .offset = startpos,
5133                         .count = numtowrite,
5134                 };
5135                 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5136                 if (NT_STATUS_V(status)) {
5137                         reply_nterror(req, status);
5138                         goto out;
5139                 }
5140         }
5141
5142         reply_outbuf(req, 1, 0);
5143
5144         SSVAL(req->outbuf,smb_vwv0,nwritten);
5145
5146         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5147                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5148
5149 out:
5150         END_PROFILE(SMBwriteunlock);
5151         return;
5152 }
5153
5154 #undef DBGC_CLASS
5155 #define DBGC_CLASS DBGC_ALL
5156
5157 /****************************************************************************
5158  Reply to a write.
5159 ****************************************************************************/
5160
5161 void reply_write(struct smb_request *req)
5162 {
5163         connection_struct *conn = req->conn;
5164         size_t numtowrite;
5165         size_t remaining;
5166         ssize_t nwritten = -1;
5167         off_t startpos;
5168         const char *data;
5169         files_struct *fsp;
5170         struct lock_struct lock;
5171         NTSTATUS status;
5172         int saved_errno = 0;
5173
5174         START_PROFILE(SMBwrite);
5175
5176         if (req->wct < 5) {
5177                 END_PROFILE(SMBwrite);
5178                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5179                 return;
5180         }
5181
5182         /* If it's an IPC, pass off the pipe handler. */
5183         if (IS_IPC(conn)) {
5184                 reply_pipe_write(req);
5185                 END_PROFILE(SMBwrite);
5186                 return;
5187         }
5188
5189         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5190
5191         if (!check_fsp(conn, req, fsp)) {
5192                 END_PROFILE(SMBwrite);
5193                 return;
5194         }
5195
5196         if (!CHECK_WRITE(fsp)) {
5197                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5198                 END_PROFILE(SMBwrite);
5199                 return;
5200         }
5201
5202         numtowrite = SVAL(req->vwv+1, 0);
5203         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5204         data = (const char *)req->buf + 3;
5205
5206         /*
5207          * Ensure client isn't asking us to write more than
5208          * they sent. CVE-2017-12163.
5209          */
5210         remaining = smbreq_bufrem(req, data);
5211         if (numtowrite > remaining) {
5212                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213                 END_PROFILE(SMBwrite);
5214                 return;
5215         }
5216
5217         if (!fsp->print_file) {
5218                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5219                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5220                         &lock);
5221
5222                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5223                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5224                         END_PROFILE(SMBwrite);
5225                         return;
5226                 }
5227         }
5228
5229         /*
5230          * X/Open SMB protocol says that if smb_vwv1 is
5231          * zero then the file size should be extended or
5232          * truncated to the size given in smb_vwv[2-3].
5233          */
5234
5235         if(numtowrite == 0) {
5236                 /*
5237                  * This is actually an allocate call, and set EOF. JRA.
5238                  */
5239                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5240                 if (nwritten < 0) {
5241                         reply_nterror(req, NT_STATUS_DISK_FULL);
5242                         goto out;
5243                 }
5244                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5245                 if (nwritten < 0) {
5246                         reply_nterror(req, NT_STATUS_DISK_FULL);
5247                         goto out;
5248                 }
5249                 trigger_write_time_update_immediate(fsp);
5250         } else {
5251                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5252         }
5253
5254         status = sync_file(conn, fsp, False);
5255         if (!NT_STATUS_IS_OK(status)) {
5256                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5257                          fsp_str_dbg(fsp), nt_errstr(status)));
5258                 reply_nterror(req, status);
5259                 goto out;
5260         }
5261
5262         if(nwritten < 0) {
5263                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5264                 goto out;
5265         }
5266
5267         if((nwritten == 0) && (numtowrite != 0)) {
5268                 reply_nterror(req, NT_STATUS_DISK_FULL);
5269                 goto out;
5270         }
5271
5272         reply_outbuf(req, 1, 0);
5273
5274         SSVAL(req->outbuf,smb_vwv0,nwritten);
5275
5276         if (nwritten < (ssize_t)numtowrite) {
5277                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5278                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5279         }
5280
5281         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5282
5283 out:
5284         END_PROFILE(SMBwrite);
5285         return;
5286 }
5287
5288 /****************************************************************************
5289  Ensure a buffer is a valid writeX for recvfile purposes.
5290 ****************************************************************************/
5291
5292 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5293                                                 (2*14) + /* word count (including bcc) */ \
5294                                                 1 /* pad byte */)
5295
5296 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5297                             const uint8_t *inbuf)
5298 {
5299         size_t numtowrite;
5300         unsigned int doff = 0;
5301         size_t len = smb_len_large(inbuf);
5302         uint16_t fnum;
5303         struct smbXsrv_open *op = NULL;
5304         struct files_struct *fsp = NULL;
5305         NTSTATUS status;
5306
5307         if (is_encrypted_packet(inbuf)) {
5308                 /* Can't do this on encrypted
5309                  * connections. */
5310                 return false;
5311         }
5312
5313         if (CVAL(inbuf,smb_com) != SMBwriteX) {
5314                 return false;
5315         }
5316
5317         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5318                         CVAL(inbuf,smb_wct) != 14) {
5319                 DEBUG(10,("is_valid_writeX_buffer: chained or "
5320                         "invalid word length.\n"));
5321                 return false;
5322         }
5323
5324         fnum = SVAL(inbuf, smb_vwv2);
5325         status = smb1srv_open_lookup(xconn,
5326                                      fnum,
5327                                      0, /* now */
5328                                      &op);
5329         if (!NT_STATUS_IS_OK(status)) {
5330                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5331                 return false;
5332         }
5333         fsp = op->compat;
5334         if (fsp == NULL) {
5335                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5336                 return false;
5337         }
5338         if (fsp->conn == NULL) {
5339                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5340                 return false;
5341         }
5342
5343         if (IS_IPC(fsp->conn)) {
5344                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5345                 return false;
5346         }
5347         if (IS_PRINT(fsp->conn)) {
5348                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5349                 return false;
5350         }
5351         if (fsp->base_fsp != NULL) {
5352                 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5353                 return false;
5354         }
5355         doff = SVAL(inbuf,smb_vwv11);
5356
5357         numtowrite = SVAL(inbuf,smb_vwv10);
5358
5359         if (len > doff && len - doff > 0xFFFF) {
5360                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5361         }
5362
5363         if (numtowrite == 0) {
5364                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5365                 return false;
5366         }
5367
5368         /* Ensure the sizes match up. */
5369         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5370                 /* no pad byte...old smbclient :-( */
5371                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5372                         (unsigned int)doff,
5373                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5374                 return false;
5375         }
5376
5377         if (len - doff != numtowrite) {
5378                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5379                         "len = %u, doff = %u, numtowrite = %u\n",
5380                         (unsigned int)len,
5381                         (unsigned int)doff,
5382                         (unsigned int)numtowrite ));
5383                 return false;
5384         }
5385
5386         DEBUG(10,("is_valid_writeX_buffer: true "
5387                 "len = %u, doff = %u, numtowrite = %u\n",
5388                 (unsigned int)len,
5389                 (unsigned int)doff,
5390                 (unsigned int)numtowrite ));
5391
5392         return true;
5393 }
5394
5395 /****************************************************************************
5396  Reply to a write and X.
5397 ****************************************************************************/
5398
5399 void reply_write_and_X(struct smb_request *req)
5400 {
5401         connection_struct *conn = req->conn;
5402         struct smbXsrv_connection *xconn = req->xconn;
5403         files_struct *fsp;
5404         struct lock_struct lock;
5405         off_t startpos;
5406         size_t numtowrite;
5407         bool write_through;
5408         ssize_t nwritten;
5409         unsigned int smb_doff;
5410         unsigned int smblen;
5411         const char *data;
5412         NTSTATUS status;
5413         int saved_errno = 0;
5414
5415         START_PROFILE(SMBwriteX);
5416
5417         if ((req->wct != 12) && (req->wct != 14)) {
5418                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5419                 goto out;
5420         }
5421
5422         numtowrite = SVAL(req->vwv+10, 0);
5423         smb_doff = SVAL(req->vwv+11, 0);
5424         smblen = smb_len(req->inbuf);
5425
5426         if (req->unread_bytes > 0xFFFF ||
5427                         (smblen > smb_doff &&
5428                                 smblen - smb_doff > 0xFFFF)) {
5429                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5430         }
5431
5432         if (req->unread_bytes) {
5433                 /* Can't do a recvfile write on IPC$ */
5434                 if (IS_IPC(conn)) {
5435                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5436                         goto out;
5437                 }
5438                 if (numtowrite != req->unread_bytes) {
5439                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5440                         goto out;
5441                 }
5442         } else {
5443                 /*
5444                  * This already protects us against CVE-2017-12163.
5445                  */
5446                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5447                                 smb_doff + numtowrite > smblen) {
5448                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5449                         goto out;
5450                 }
5451         }
5452
5453         /* If it's an IPC, pass off the pipe handler. */
5454         if (IS_IPC(conn)) {
5455                 if (req->unread_bytes) {
5456                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5457                         goto out;
5458                 }
5459                 reply_pipe_write_and_X(req);
5460                 goto out;
5461         }
5462
5463         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5464         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5465         write_through = BITSETW(req->vwv+7,0);
5466
5467         if (!check_fsp(conn, req, fsp)) {
5468                 goto out;
5469         }
5470
5471         if (!CHECK_WRITE(fsp)) {
5472                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5473                 goto out;
5474         }
5475
5476         data = smb_base(req->inbuf) + smb_doff;
5477
5478         if(req->wct == 14) {
5479                 /*
5480                  * This is a large offset (64 bit) write.
5481                  */
5482                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5483
5484         }
5485
5486         /* X/Open SMB protocol says that, unlike SMBwrite
5487         if the length is zero then NO truncation is
5488         done, just a write of zero. To truncate a file,
5489         use SMBwrite. */
5490
5491         if(numtowrite == 0) {
5492                 nwritten = 0;
5493         } else {
5494                 if (req->unread_bytes == 0) {
5495                         status = schedule_aio_write_and_X(conn,
5496                                                 req,
5497                                                 fsp,
5498                                                 data,
5499                                                 startpos,
5500                                                 numtowrite);
5501
5502                         if (NT_STATUS_IS_OK(status)) {
5503                                 /* write scheduled - we're done. */
5504                                 goto out;
5505                         }
5506                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5507                                 /* Real error - report to client. */
5508                                 reply_nterror(req, status);
5509                                 goto out;
5510                         }
5511                         /* NT_STATUS_RETRY - fall through to sync write. */
5512                 }
5513
5514                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5515                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5516                     &lock);
5517
5518                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5519                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5520                         goto out;
5521                 }
5522
5523                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5524                 saved_errno = errno;
5525         }
5526
5527         if(nwritten < 0) {
5528                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5529                 goto out;
5530         }
5531
5532         if((nwritten == 0) && (numtowrite != 0)) {
5533                 reply_nterror(req, NT_STATUS_DISK_FULL);
5534                 goto out;
5535         }
5536
5537         reply_outbuf(req, 6, 0);
5538         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5539         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
5540         SSVAL(req->outbuf,smb_vwv2,nwritten);
5541         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5542
5543         DEBUG(3,("writeX %s num=%d wrote=%d\n",
5544                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5545
5546         status = sync_file(conn, fsp, write_through);
5547         if (!NT_STATUS_IS_OK(status)) {
5548                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5549                          fsp_str_dbg(fsp), nt_errstr(status)));
5550                 reply_nterror(req, status);
5551                 goto out;
5552         }
5553
5554         END_PROFILE(SMBwriteX);
5555         return;
5556
5557 out:
5558         if (req->unread_bytes) {
5559                 /* writeX failed. drain socket. */
5560                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5561                                 req->unread_bytes) {
5562                         smb_panic("failed to drain pending bytes");
5563                 }
5564                 req->unread_bytes = 0;
5565         }
5566
5567         END_PROFILE(SMBwriteX);
5568         return;
5569 }
5570
5571 /****************************************************************************
5572  Reply to a lseek.
5573 ****************************************************************************/
5574
5575 void reply_lseek(struct smb_request *req)
5576 {
5577         connection_struct *conn = req->conn;
5578         off_t startpos;
5579         off_t res= -1;
5580         int mode,umode;
5581         files_struct *fsp;
5582         NTSTATUS status;
5583
5584         START_PROFILE(SMBlseek);
5585
5586         if (req->wct < 4) {
5587                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5588                 END_PROFILE(SMBlseek);
5589                 return;
5590         }
5591
5592         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5593
5594         if (!check_fsp(conn, req, fsp)) {
5595                 return;
5596         }
5597
5598         mode = SVAL(req->vwv+1, 0) & 3;
5599         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5600         startpos = (off_t)IVALS(req->vwv+2, 0);
5601
5602         switch (mode) {
5603                 case 0:
5604                         umode = SEEK_SET;
5605                         res = startpos;
5606                         break;
5607                 case 1:
5608                         umode = SEEK_CUR;
5609                         res = fsp->fh->pos + startpos;
5610                         break;
5611                 case 2:
5612                         umode = SEEK_END;
5613                         break;
5614                 default:
5615                         umode = SEEK_SET;
5616                         res = startpos;
5617                         break;
5618         }
5619
5620         if (umode == SEEK_END) {
5621                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5622                         if(errno == EINVAL) {
5623                                 off_t current_pos = startpos;
5624
5625                                 status = vfs_stat_fsp(fsp);
5626                                 if (!NT_STATUS_IS_OK(status)) {
5627                                         reply_nterror(req, status);
5628                                         END_PROFILE(SMBlseek);
5629                                         return;
5630                                 }
5631
5632                                 current_pos += fsp->fsp_name->st.st_ex_size;
5633                                 if(current_pos < 0)
5634                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5635                         }
5636                 }
5637
5638                 if(res == -1) {
5639                         reply_nterror(req, map_nt_error_from_unix(errno));
5640                         END_PROFILE(SMBlseek);
5641                         return;
5642                 }
5643         }
5644
5645         fsp->fh->pos = res;
5646
5647         reply_outbuf(req, 2, 0);
5648         SIVAL(req->outbuf,smb_vwv0,res);
5649
5650         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5651                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5652
5653         END_PROFILE(SMBlseek);
5654         return;
5655 }
5656
5657 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5658                                              void *private_data)
5659 {
5660         connection_struct *conn = talloc_get_type_abort(
5661                 private_data, connection_struct);
5662
5663         if (conn != fsp->conn) {
5664                 return NULL;
5665         }
5666         if (fsp->fh->fd == -1) {
5667                 return NULL;
5668         }
5669         sync_file(conn, fsp, True /* write through */);
5670
5671         if (fsp->fsp_flags.modified) {
5672                 trigger_write_time_update_immediate(fsp);
5673         }
5674
5675         return NULL;
5676 }
5677
5678 /****************************************************************************
5679  Reply to a flush.
5680 ****************************************************************************/
5681
5682 void reply_flush(struct smb_request *req)
5683 {
5684         connection_struct *conn = req->conn;
5685         uint16_t fnum;
5686         files_struct *fsp;
5687
5688         START_PROFILE(SMBflush);
5689
5690         if (req->wct < 1) {
5691                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5692                 return;
5693         }
5694
5695         fnum = SVAL(req->vwv+0, 0);
5696         fsp = file_fsp(req, fnum);
5697
5698         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5699                 return;
5700         }
5701
5702         if (!fsp) {
5703                 files_forall(req->sconn, file_sync_one_fn, conn);
5704         } else {
5705                 NTSTATUS status = sync_file(conn, fsp, True);
5706                 if (!NT_STATUS_IS_OK(status)) {
5707                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5708                                 fsp_str_dbg(fsp), nt_errstr(status)));
5709                         reply_nterror(req, status);
5710                         END_PROFILE(SMBflush);
5711                         return;
5712                 }
5713                 if (fsp->fsp_flags.modified) {
5714                         trigger_write_time_update_immediate(fsp);
5715                 }
5716         }
5717
5718         reply_outbuf(req, 0, 0);
5719
5720         DEBUG(3,("flush\n"));
5721         END_PROFILE(SMBflush);
5722         return;
5723 }
5724
5725 /****************************************************************************
5726  Reply to a exit.
5727  conn POINTER CAN BE NULL HERE !
5728 ****************************************************************************/
5729
5730 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5731 static void reply_exit_done(struct tevent_req *req);
5732
5733 void reply_exit(struct smb_request *smb1req)
5734 {
5735         struct tevent_req *req;
5736
5737         /*
5738          * Don't setup the profile charge here, take
5739          * it in reply_exit_done(). Not strictly correct
5740          * but better than the other SMB1 async
5741          * code that double-charges at the moment.
5742          */
5743         req = reply_exit_send(smb1req);
5744         if (req == NULL) {
5745                 /* Not going async, profile here. */
5746                 START_PROFILE(SMBexit);
5747                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5748                 END_PROFILE(SMBexit);
5749                 return;
5750         }
5751
5752         /* We're async. This will complete later. */
5753         tevent_req_set_callback(req, reply_exit_done, smb1req);
5754         return;
5755 }
5756
5757 struct reply_exit_state {
5758         struct tevent_queue *wait_queue;
5759 };
5760
5761 static void reply_exit_wait_done(struct tevent_req *subreq);
5762
5763 /****************************************************************************
5764  Async SMB1 exit.
5765  Note, on failure here we deallocate and return NULL to allow the caller to
5766  SMB1 return an error of ERRnomem immediately.
5767 ****************************************************************************/
5768
5769 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5770 {
5771         struct tevent_req *req;
5772         struct reply_exit_state *state;
5773         struct tevent_req *subreq;
5774         files_struct *fsp;
5775         struct smbd_server_connection *sconn = smb1req->sconn;
5776
5777         req = tevent_req_create(smb1req, &state,
5778                         struct reply_exit_state);
5779         if (req == NULL) {
5780                 return NULL;
5781         }
5782         state->wait_queue = tevent_queue_create(state,
5783                                 "reply_exit_wait_queue");
5784         if (tevent_req_nomem(state->wait_queue, req)) {
5785                 TALLOC_FREE(req);
5786                 return NULL;
5787         }
5788
5789         for (fsp = sconn->files; fsp; fsp = fsp->next) {
5790                 if (fsp->file_pid != smb1req->smbpid) {
5791                         continue;
5792                 }
5793                 if (fsp->vuid != smb1req->vuid) {
5794                         continue;
5795                 }
5796                 /*
5797                  * Flag the file as close in progress.
5798                  * This will prevent any more IO being
5799                  * done on it.
5800                  */
5801                 fsp->fsp_flags.closing = true;
5802
5803                 if (fsp->num_aio_requests > 0) {
5804                         /*
5805                          * Now wait until all aio requests on this fsp are
5806                          * finished.
5807                          *
5808                          * We don't set a callback, as we just want to block the
5809                          * wait queue and the talloc_free() of fsp->aio_request
5810                          * will remove the item from the wait queue.
5811                          */
5812                         subreq = tevent_queue_wait_send(fsp->aio_requests,
5813                                                 sconn->ev_ctx,
5814                                                 state->wait_queue);
5815                         if (tevent_req_nomem(subreq, req)) {
5816                                 TALLOC_FREE(req);
5817                                 return NULL;
5818                         }
5819                 }
5820         }
5821
5822         /*
5823          * Now we add our own waiter to the end of the queue,
5824          * this way we get notified when all pending requests are finished
5825          * and reply to the outstanding SMB1 request.
5826          */
5827         subreq = tevent_queue_wait_send(state,
5828                                 sconn->ev_ctx,
5829                                 state->wait_queue);
5830         if (tevent_req_nomem(subreq, req)) {
5831                 TALLOC_FREE(req);
5832                 return NULL;
5833         }
5834
5835         /*
5836          * We're really going async - move the SMB1 request from
5837          * a talloc stackframe above us to the conn talloc-context.
5838          * We need this to stick around until the wait_done
5839          * callback is invoked.
5840          */
5841         smb1req = talloc_move(sconn, &smb1req);
5842
5843         tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5844
5845         return req;
5846 }
5847
5848 static void reply_exit_wait_done(struct tevent_req *subreq)
5849 {
5850         struct tevent_req *req = tevent_req_callback_data(
5851                 subreq, struct tevent_req);
5852
5853         tevent_queue_wait_recv(subreq);
5854         TALLOC_FREE(subreq);
5855         tevent_req_done(req);
5856 }
5857
5858 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5859 {
5860         return tevent_req_simple_recv_ntstatus(req);
5861 }
5862
5863 static void reply_exit_done(struct tevent_req *req)
5864 {
5865         struct smb_request *smb1req = tevent_req_callback_data(
5866                 req, struct smb_request);
5867         struct smbd_server_connection *sconn = smb1req->sconn;
5868         struct smbXsrv_connection *xconn = smb1req->xconn;
5869         NTTIME now = timeval_to_nttime(&smb1req->request_time);
5870         struct smbXsrv_session *session = NULL;
5871         files_struct *fsp, *next;
5872         NTSTATUS status;
5873
5874         /*
5875          * Take the profile charge here. Not strictly
5876          * correct but better than the other SMB1 async
5877          * code that double-charges at the moment.
5878          */
5879         START_PROFILE(SMBexit);
5880
5881         status = reply_exit_recv(req);
5882         TALLOC_FREE(req);
5883         if (!NT_STATUS_IS_OK(status)) {
5884                 TALLOC_FREE(smb1req);
5885                 END_PROFILE(SMBexit);
5886                 exit_server(__location__ ": reply_exit_recv failed");
5887                 return;
5888         }
5889
5890         /*
5891          * Ensure the session is still valid.
5892          */
5893         status = smb1srv_session_lookup(xconn,
5894                                         smb1req->vuid,
5895                                         now,
5896                                         &session);
5897         if (!NT_STATUS_IS_OK(status)) {
5898                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5899                 smb_request_done(smb1req);
5900                 END_PROFILE(SMBexit);
5901         }
5902
5903         /*
5904          * Ensure the vuid is still valid - no one
5905          * called reply_ulogoffX() in the meantime.
5906          * reply_exit() doesn't have AS_USER set, so
5907          * use set_current_user_info() directly.
5908          * This is the same logic as in switch_message().
5909          */
5910         if (session->global->auth_session_info != NULL) {
5911                 set_current_user_info(
5912                         session->global->auth_session_info->unix_info->sanitized_username,
5913                         session->global->auth_session_info->unix_info->unix_name,
5914                         session->global->auth_session_info->info->domain_name);
5915         }
5916
5917         /* No more aio - do the actual closes. */
5918         for (fsp = sconn->files; fsp; fsp = next) {
5919                 bool ok;
5920                 next = fsp->next;
5921
5922                 if (fsp->file_pid != smb1req->smbpid) {
5923                         continue;
5924                 }
5925                 if (fsp->vuid != smb1req->vuid) {
5926                         continue;
5927                 }
5928                 if (!fsp->fsp_flags.closing) {
5929                         continue;
5930                 }
5931
5932                 /*
5933                  * reply_exit() has the DO_CHDIR flag set.
5934                  */
5935                 ok = chdir_current_service(fsp->conn);
5936                 if (!ok) {
5937                         reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5938                         smb_request_done(smb1req);
5939                         END_PROFILE(SMBexit);
5940                 }
5941                 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5942         }
5943
5944         reply_outbuf(smb1req, 0, 0);
5945         /*
5946          * The following call is needed to push the
5947          * reply data back out the socket after async
5948          * return. Plus it frees smb1req.
5949          */
5950         smb_request_done(smb1req);
5951         DBG_INFO("reply_exit complete\n");
5952         END_PROFILE(SMBexit);
5953         return;
5954 }
5955
5956 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5957                                 files_struct *fsp);
5958 static void reply_close_done(struct tevent_req *req);
5959
5960 void reply_close(struct smb_request *smb1req)
5961 {
5962         connection_struct *conn = smb1req->conn;
5963         NTSTATUS status = NT_STATUS_OK;
5964         files_struct *fsp = NULL;
5965         START_PROFILE(SMBclose);
5966
5967         if (smb1req->wct < 3) {
5968                 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5969                 END_PROFILE(SMBclose);
5970                 return;
5971         }
5972
5973         fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5974
5975         /*
5976          * We can only use check_fsp if we know it's not a directory.
5977          */
5978
5979         if (!check_fsp_open(conn, smb1req, fsp)) {
5980                 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5981                 END_PROFILE(SMBclose);
5982                 return;
5983         }
5984
5985         DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5986                   fsp->fsp_flags.is_directory ?
5987                   "directory" : "file",
5988                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5989                   conn->num_files_open);
5990
5991         if (!fsp->fsp_flags.is_directory) {
5992                 time_t t;
5993
5994                 /*
5995                  * Take care of any time sent in the close.
5996                  */
5997
5998                 t = srv_make_unix_date3(smb1req->vwv+1);
5999                 set_close_write_time(fsp, time_t_to_full_timespec(t));
6000         }
6001
6002         if (fsp->num_aio_requests != 0) {
6003                 struct tevent_req *req;
6004
6005                 req = reply_close_send(smb1req, fsp);
6006                 if (req == NULL) {
6007                         status = NT_STATUS_NO_MEMORY;
6008                         goto done;
6009                 }
6010                 /* We're async. This will complete later. */
6011                 tevent_req_set_callback(req, reply_close_done, smb1req);
6012                 END_PROFILE(SMBclose);
6013                 return;
6014         }
6015
6016         /*
6017          * close_file() returns the unix errno if an error was detected on
6018          * close - normally this is due to a disk full error. If not then it
6019          * was probably an I/O error.
6020          */
6021
6022         status = close_file(smb1req, fsp, NORMAL_CLOSE);
6023 done:
6024         if (!NT_STATUS_IS_OK(status)) {
6025                 reply_nterror(smb1req, status);
6026                 END_PROFILE(SMBclose);
6027                 return;
6028         }
6029
6030         reply_outbuf(smb1req, 0, 0);
6031         END_PROFILE(SMBclose);
6032         return;
6033 }
6034
6035 struct reply_close_state {
6036         files_struct *fsp;
6037         struct tevent_queue *wait_queue;
6038 };
6039
6040 static void reply_close_wait_done(struct tevent_req *subreq);
6041
6042 /****************************************************************************
6043  Async SMB1 close.
6044  Note, on failure here we deallocate and return NULL to allow the caller to
6045  SMB1 return an error of ERRnomem immediately.
6046 ****************************************************************************/
6047
6048 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6049                                 files_struct *fsp)
6050 {
6051         struct tevent_req *req;
6052         struct reply_close_state *state;
6053         struct tevent_req *subreq;
6054         struct smbd_server_connection *sconn = smb1req->sconn;
6055
6056         req = tevent_req_create(smb1req, &state,
6057                         struct reply_close_state);
6058         if (req == NULL) {
6059                 return NULL;
6060         }
6061         state->wait_queue = tevent_queue_create(state,
6062                                 "reply_close_wait_queue");
6063         if (tevent_req_nomem(state->wait_queue, req)) {
6064                 TALLOC_FREE(req);
6065                 return NULL;
6066         }
6067
6068         /*
6069          * Flag the file as close in progress.
6070          * This will prevent any more IO being
6071          * done on it.
6072          */
6073         fsp->fsp_flags.closing = true;
6074
6075         /*
6076          * Now wait until all aio requests on this fsp are
6077          * finished.
6078          *
6079          * We don't set a callback, as we just want to block the
6080          * wait queue and the talloc_free() of fsp->aio_request
6081          * will remove the item from the wait queue.
6082          */
6083         subreq = tevent_queue_wait_send(fsp->aio_requests,
6084                                         sconn->ev_ctx,
6085                                         state->wait_queue);
6086         if (tevent_req_nomem(subreq, req)) {
6087                 TALLOC_FREE(req);
6088                 return NULL;
6089         }
6090
6091         /*
6092          * Now we add our own waiter to the end of the queue,
6093          * this way we get notified when all pending requests are finished
6094          * and reply to the outstanding SMB1 request.
6095          */
6096         subreq = tevent_queue_wait_send(state,
6097                                 sconn->ev_ctx,
6098                                 state->wait_queue);
6099         if (tevent_req_nomem(subreq, req)) {
6100                 TALLOC_FREE(req);
6101                 return NULL;
6102         }
6103
6104         /*
6105          * We're really going async - move the SMB1 request from
6106          * a talloc stackframe above us to the conn talloc-context.
6107          * We need this to stick around until the wait_done
6108          * callback is invoked.
6109          */
6110         smb1req = talloc_move(sconn, &smb1req);
6111
6112         tevent_req_set_callback(subreq, reply_close_wait_done, req);
6113
6114         return req;
6115 }
6116
6117 static void reply_close_wait_done(struct tevent_req *subreq)
6118 {
6119         struct tevent_req *req = tevent_req_callback_data(
6120                 subreq, struct tevent_req);
6121
6122         tevent_queue_wait_recv(subreq);
6123         TALLOC_FREE(subreq);
6124         tevent_req_done(req);
6125 }
6126
6127 static NTSTATUS reply_close_recv(struct tevent_req *req)
6128 {
6129         return tevent_req_simple_recv_ntstatus(req);
6130 }
6131
6132 static void reply_close_done(struct tevent_req *req)
6133 {
6134         struct smb_request *smb1req = tevent_req_callback_data(
6135                         req, struct smb_request);
6136         struct reply_close_state *state = tevent_req_data(req,
6137                                                 struct reply_close_state);
6138         NTSTATUS status;
6139
6140         status = reply_close_recv(req);
6141         TALLOC_FREE(req);
6142         if (!NT_STATUS_IS_OK(status)) {
6143                 TALLOC_FREE(smb1req);
6144                 exit_server(__location__ ": reply_close_recv failed");
6145                 return;
6146         }
6147
6148         status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6149         if (NT_STATUS_IS_OK(status)) {
6150                 reply_outbuf(smb1req, 0, 0);
6151         } else {
6152                 reply_nterror(smb1req, status);
6153         }
6154         /*
6155          * The following call is needed to push the
6156          * reply data back out the socket after async
6157          * return. Plus it frees smb1req.
6158          */
6159         smb_request_done(smb1req);
6160 }
6161
6162 /****************************************************************************
6163  Reply to a writeclose (Core+ protocol).
6164 ****************************************************************************/
6165
6166 void reply_writeclose(struct smb_request *req)
6167 {
6168         connection_struct *conn = req->conn;
6169         size_t numtowrite;
6170         size_t remaining;
6171         ssize_t nwritten = -1;
6172         NTSTATUS close_status = NT_STATUS_OK;
6173         off_t startpos;
6174         const char *data;
6175         struct timespec mtime;
6176         files_struct *fsp;
6177         struct lock_struct lock;
6178
6179         START_PROFILE(SMBwriteclose);
6180
6181         if (req->wct < 6) {
6182                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6183                 END_PROFILE(SMBwriteclose);
6184                 return;
6185         }
6186
6187         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6188
6189         if (!check_fsp(conn, req, fsp)) {
6190                 END_PROFILE(SMBwriteclose);
6191                 return;
6192         }
6193         if (!CHECK_WRITE(fsp)) {
6194                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6195                 END_PROFILE(SMBwriteclose);
6196                 return;
6197         }
6198
6199         numtowrite = SVAL(req->vwv+1, 0);
6200         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6201         mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6202         data = (const char *)req->buf + 1;
6203
6204         /*
6205          * Ensure client isn't asking us to write more than
6206          * they sent. CVE-2017-12163.
6207          */
6208         remaining = smbreq_bufrem(req, data);
6209         if (numtowrite > remaining) {
6210                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6211                 END_PROFILE(SMBwriteclose);
6212                 return;
6213         }
6214
6215         if (fsp->print_file == NULL) {
6216                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6217                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6218                     &lock);
6219
6220                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6221                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6222                         END_PROFILE(SMBwriteclose);
6223                         return;
6224                 }
6225         }
6226
6227         nwritten = write_file(req,fsp,data,startpos,numtowrite);
6228
6229         set_close_write_time(fsp, mtime);
6230
6231         /*
6232          * More insanity. W2K only closes the file if writelen > 0.
6233          * JRA.
6234          */
6235
6236         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6237                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6238                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6239
6240         if (numtowrite) {
6241                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6242                          "file %s\n", fsp_str_dbg(fsp)));
6243                 close_status = close_file(req, fsp, NORMAL_CLOSE);
6244                 fsp = NULL;
6245         }
6246
6247         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6248                 reply_nterror(req, NT_STATUS_DISK_FULL);
6249                 goto out;
6250         }
6251
6252         if(!NT_STATUS_IS_OK(close_status)) {
6253                 reply_nterror(req, close_status);
6254                 goto out;
6255         }
6256
6257         reply_outbuf(req, 1, 0);
6258
6259         SSVAL(req->outbuf,smb_vwv0,nwritten);
6260
6261 out:
6262
6263         END_PROFILE(SMBwriteclose);
6264         return;
6265 }
6266
6267 #undef DBGC_CLASS
6268 #define DBGC_CLASS DBGC_LOCKING
6269
6270 /****************************************************************************
6271  Reply to a lock.
6272 ****************************************************************************/
6273
6274 static void reply_lock_done(struct tevent_req *subreq);
6275
6276 void reply_lock(struct smb_request *req)
6277 {
6278         struct tevent_req *subreq = NULL;
6279         connection_struct *conn = req->conn;
6280         files_struct *fsp;
6281         struct smbd_lock_element *lck = NULL;
6282
6283         START_PROFILE(SMBlock);
6284
6285         if (req->wct < 5) {
6286                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6287                 END_PROFILE(SMBlock);
6288                 return;
6289         }
6290
6291         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6292
6293         if (!check_fsp(conn, req, fsp)) {
6294                 END_PROFILE(SMBlock);
6295                 return;
6296         }
6297
6298         lck = talloc(req, struct smbd_lock_element);
6299         if (lck == NULL) {
6300                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6301                 END_PROFILE(SMBlock);
6302                 return;
6303         }
6304
6305         *lck = (struct smbd_lock_element) {
6306                 .req_guid = smbd_request_guid(req, 0),
6307                 .smblctx = req->smbpid,
6308                 .brltype = WRITE_LOCK,
6309                 .count = IVAL(req->vwv+1, 0),
6310                 .offset = IVAL(req->vwv+3, 0),
6311         };
6312
6313         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6314                    fsp->fh->fd,
6315                    fsp_fnum_dbg(fsp),
6316                    lck->offset,
6317                    lck->count);
6318
6319         subreq = smbd_smb1_do_locks_send(
6320                 fsp,
6321                 req->sconn->ev_ctx,
6322                 &req,
6323                 fsp,
6324                 0,
6325                 false,          /* large_offset */
6326                 WINDOWS_LOCK,
6327                 1,
6328                 lck);
6329         if (subreq == NULL) {
6330                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6331                 END_PROFILE(SMBlock);
6332                 return;
6333         }
6334         tevent_req_set_callback(subreq, reply_lock_done, NULL);
6335         END_PROFILE(SMBlock);
6336 }
6337
6338 static void reply_lock_done(struct tevent_req *subreq)
6339 {
6340         struct smb_request *req = NULL;
6341         NTSTATUS status;
6342         bool ok;
6343
6344         START_PROFILE(SMBlock);
6345
6346         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6347         SMB_ASSERT(ok);
6348
6349         status = smbd_smb1_do_locks_recv(subreq);
6350         TALLOC_FREE(subreq);
6351
6352         if (NT_STATUS_IS_OK(status)) {
6353                 reply_outbuf(req, 0, 0);
6354         } else {
6355                 reply_nterror(req, status);
6356         }
6357
6358         ok = srv_send_smb(req->xconn,
6359                           (char *)req->outbuf,
6360                           true,
6361                           req->seqnum+1,
6362                           IS_CONN_ENCRYPTED(req->conn),
6363                           NULL);
6364         if (!ok) {
6365                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6366         }
6367         TALLOC_FREE(req);
6368         END_PROFILE(SMBlock);
6369 }
6370
6371 /****************************************************************************
6372  Reply to a unlock.
6373 ****************************************************************************/
6374
6375 void reply_unlock(struct smb_request *req)
6376 {
6377         connection_struct *conn = req->conn;
6378         NTSTATUS status;
6379         files_struct *fsp;
6380         struct smbd_lock_element lck;
6381
6382         START_PROFILE(SMBunlock);
6383
6384         if (req->wct < 5) {
6385                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6386                 END_PROFILE(SMBunlock);
6387                 return;
6388         }
6389
6390         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6391
6392         if (!check_fsp(conn, req, fsp)) {
6393                 END_PROFILE(SMBunlock);
6394                 return;
6395         }
6396
6397         lck = (struct smbd_lock_element) {
6398                 .req_guid = smbd_request_guid(req, 0),
6399                 .smblctx = req->smbpid,
6400                 .brltype = UNLOCK_LOCK,
6401                 .offset = IVAL(req->vwv+3, 0),
6402                 .count = IVAL(req->vwv+1, 0),
6403         };
6404
6405         status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6406
6407         if (!NT_STATUS_IS_OK(status)) {
6408                 reply_nterror(req, status);
6409                 END_PROFILE(SMBunlock);
6410                 return;
6411         }
6412
6413         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6414                    fsp->fh->fd,
6415                    fsp_fnum_dbg(fsp),
6416                    lck.offset,
6417                    lck.count);
6418
6419         reply_outbuf(req, 0, 0);
6420
6421         END_PROFILE(SMBunlock);
6422         return;
6423 }
6424
6425 #undef DBGC_CLASS
6426 #define DBGC_CLASS DBGC_ALL
6427
6428 /****************************************************************************
6429  Reply to a tdis.
6430  conn POINTER CAN BE NULL HERE !
6431 ****************************************************************************/
6432
6433 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6434 static void reply_tdis_done(struct tevent_req *req);
6435
6436 void reply_tdis(struct smb_request *smb1req)
6437 {
6438         connection_struct *conn = smb1req->conn;
6439         struct tevent_req *req;
6440
6441         /*
6442          * Don't setup the profile charge here, take
6443          * it in reply_tdis_done(). Not strictly correct
6444          * but better than the other SMB1 async
6445          * code that double-charges at the moment.
6446          */
6447
6448         if (conn == NULL) {
6449                 /* Not going async, profile here. */
6450                 START_PROFILE(SMBtdis);
6451                 DBG_INFO("Invalid connection in tdis\n");
6452                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6453                 END_PROFILE(SMBtdis);
6454                 return;
6455         }
6456
6457         req = reply_tdis_send(smb1req);
6458         if (req == NULL) {
6459                 /* Not going async, profile here. */
6460                 START_PROFILE(SMBtdis);
6461                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6462                 END_PROFILE(SMBtdis);
6463                 return;
6464         }
6465         /* We're async. This will complete later. */
6466         tevent_req_set_callback(req, reply_tdis_done, smb1req);
6467         return;
6468 }
6469
6470 struct reply_tdis_state {
6471         struct tevent_queue *wait_queue;
6472 };
6473
6474 static void reply_tdis_wait_done(struct tevent_req *subreq);
6475
6476 /****************************************************************************
6477  Async SMB1 tdis.
6478  Note, on failure here we deallocate and return NULL to allow the caller to
6479  SMB1 return an error of ERRnomem immediately.
6480 ****************************************************************************/
6481
6482 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6483 {
6484         struct tevent_req *req;
6485         struct reply_tdis_state *state;
6486         struct tevent_req *subreq;
6487         connection_struct *conn = smb1req->conn;
6488         files_struct *fsp;
6489
6490         req = tevent_req_create(smb1req, &state,
6491                         struct reply_tdis_state);
6492         if (req == NULL) {
6493                 return NULL;
6494         }
6495         state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6496         if (tevent_req_nomem(state->wait_queue, req)) {
6497                 TALLOC_FREE(req);
6498                 return NULL;
6499         }
6500
6501         /*
6502          * Make sure that no new request will be able to use this tcon.
6503          * This ensures that once all outstanding fsp->aio_requests
6504          * on this tcon are done, we are safe to close it.
6505          */
6506         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6507
6508         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6509                 if (fsp->conn != conn) {
6510                         continue;
6511                 }
6512                 /*
6513                  * Flag the file as close in progress.
6514                  * This will prevent any more IO being
6515                  * done on it. Not strictly needed, but
6516                  * doesn't hurt to flag it as closing.
6517                  */
6518                 fsp->fsp_flags.closing = true;
6519
6520                 if (fsp->num_aio_requests > 0) {
6521                         /*
6522                          * Now wait until all aio requests on this fsp are
6523                          * finished.
6524                          *
6525                          * We don't set a callback, as we just want to block the
6526                          * wait queue and the talloc_free() of fsp->aio_request
6527                          * will remove the item from the wait queue.
6528                          */
6529                         subreq = tevent_queue_wait_send(fsp->aio_requests,
6530                                                 conn->sconn->ev_ctx,
6531                                                 state->wait_queue);
6532                         if (tevent_req_nomem(subreq, req)) {
6533                                 TALLOC_FREE(req);
6534                                 return NULL;
6535                         }
6536                 }
6537         }
6538
6539         /*
6540          * Now we add our own waiter to the end of the queue,
6541          * this way we get notified when all pending requests are finished
6542          * and reply to the outstanding SMB1 request.
6543          */
6544         subreq = tevent_queue_wait_send(state,
6545                                 conn->sconn->ev_ctx,
6546                                 state->wait_queue);
6547         if (tevent_req_nomem(subreq, req)) {
6548                 TALLOC_FREE(req);
6549                 return NULL;
6550         }
6551
6552         /*
6553          * We're really going async - move the SMB1 request from
6554          * a talloc stackframe above us to the sconn talloc-context.
6555          * We need this to stick around until the wait_done
6556          * callback is invoked.
6557          */
6558         smb1req = talloc_move(smb1req->sconn, &smb1req);
6559
6560         tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6561
6562         return req;
6563 }
6564
6565 static void reply_tdis_wait_done(struct tevent_req *subreq)
6566 {
6567         struct tevent_req *req = tevent_req_callback_data(
6568                 subreq, struct tevent_req);
6569
6570         tevent_queue_wait_recv(subreq);
6571         TALLOC_FREE(subreq);
6572         tevent_req_done(req);
6573 }
6574
6575 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6576 {
6577         return tevent_req_simple_recv_ntstatus(req);
6578 }
6579
6580 static void reply_tdis_done(struct tevent_req *req)
6581 {
6582         struct smb_request *smb1req = tevent_req_callback_data(
6583                 req, struct smb_request);
6584         NTSTATUS status;
6585         struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6586         bool ok;
6587
6588         /*
6589          * Take the profile charge here. Not strictly
6590          * correct but better than the other SMB1 async
6591          * code that double-charges at the moment.
6592          */
6593         START_PROFILE(SMBtdis);
6594
6595         status = reply_tdis_recv(req);
6596         TALLOC_FREE(req);
6597         if (!NT_STATUS_IS_OK(status)) {
6598                 TALLOC_FREE(smb1req);
6599                 END_PROFILE(SMBtdis);
6600                 exit_server(__location__ ": reply_tdis_recv failed");
6601                 return;
6602         }
6603
6604         /*
6605          * As we've been awoken, we may have changed
6606          * directory in the meantime.
6607          * reply_tdis() has the DO_CHDIR flag set.
6608          */
6609         ok = chdir_current_service(smb1req->conn);
6610         if (!ok) {
6611                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6612                 smb_request_done(smb1req);
6613                 END_PROFILE(SMBtdis);
6614         }
6615
6616         status = smbXsrv_tcon_disconnect(tcon,
6617                                          smb1req->vuid);
6618         if (!NT_STATUS_IS_OK(status)) {
6619                 TALLOC_FREE(smb1req);
6620                 END_PROFILE(SMBtdis);
6621                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6622                 return;
6623         }
6624
6625         /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6626         smb1req->conn = NULL;
6627
6628         TALLOC_FREE(tcon);
6629
6630         reply_outbuf(smb1req, 0, 0);
6631         /*
6632          * The following call is needed to push the
6633          * reply data back out the socket after async
6634          * return. Plus it frees smb1req.
6635          */
6636         smb_request_done(smb1req);
6637         END_PROFILE(SMBtdis);
6638 }
6639
6640 /****************************************************************************
6641  Reply to a echo.
6642  conn POINTER CAN BE NULL HERE !
6643 ****************************************************************************/
6644
6645 void reply_echo(struct smb_request *req)
6646 {
6647         connection_struct *conn = req->conn;
6648         struct smb_perfcount_data local_pcd;
6649         struct smb_perfcount_data *cur_pcd;
6650         int smb_reverb;
6651         int seq_num;
6652
6653         START_PROFILE(SMBecho);
6654
6655         smb_init_perfcount_data(&local_pcd);
6656
6657         if (req->wct < 1) {
6658                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6659                 END_PROFILE(SMBecho);
6660                 return;
6661         }
6662
6663         smb_reverb = SVAL(req->vwv+0, 0);
6664
6665         reply_outbuf(req, 1, req->buflen);
6666
6667         /* copy any incoming data back out */
6668         if (req->buflen > 0) {
6669                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6670         }
6671
6672         if (smb_reverb > 100) {
6673                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6674                 smb_reverb = 100;
6675         }
6676
6677         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6678
6679                 /* this makes sure we catch the request pcd */
6680                 if (seq_num == smb_reverb) {
6681                         cur_pcd = &req->pcd;
6682                 } else {
6683                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6684                         cur_pcd = &local_pcd;
6685                 }
6686
6687                 SSVAL(req->outbuf,smb_vwv0,seq_num);
6688
6689                 show_msg((char *)req->outbuf);
6690                 if (!srv_send_smb(req->xconn,
6691                                 (char *)req->outbuf,
6692                                 true, req->seqnum+1,
6693                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6694                                 cur_pcd))
6695                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
6696         }
6697
6698         DEBUG(3,("echo %d times\n", smb_reverb));
6699
6700         TALLOC_FREE(req->outbuf);
6701
6702         END_PROFILE(SMBecho);
6703         return;
6704 }
6705
6706 /****************************************************************************
6707  Reply to a printopen.
6708 ****************************************************************************/
6709
6710 void reply_printopen(struct smb_request *req)
6711 {
6712         connection_struct *conn = req->conn;
6713         files_struct *fsp;
6714         NTSTATUS status;
6715
6716         START_PROFILE(SMBsplopen);
6717
6718         if (req->wct < 2) {
6719                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6720                 END_PROFILE(SMBsplopen);
6721                 return;
6722         }
6723
6724         if (!CAN_PRINT(conn)) {
6725                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6726                 END_PROFILE(SMBsplopen);
6727                 return;
6728         }
6729
6730         status = file_new(req, conn, &fsp);
6731         if(!NT_STATUS_IS_OK(status)) {
6732                 reply_nterror(req, status);
6733                 END_PROFILE(SMBsplopen);
6734                 return;
6735         }
6736
6737         /* Open for exclusive use, write only. */
6738         status = print_spool_open(fsp, NULL, req->vuid);
6739
6740         if (!NT_STATUS_IS_OK(status)) {
6741                 file_free(req, fsp);
6742                 reply_nterror(req, status);
6743                 END_PROFILE(SMBsplopen);
6744                 return;
6745         }
6746
6747         reply_outbuf(req, 1, 0);
6748         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6749
6750         DEBUG(3,("openprint fd=%d %s\n",
6751                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6752
6753         END_PROFILE(SMBsplopen);
6754         return;
6755 }
6756
6757 /****************************************************************************
6758  Reply to a printclose.
6759 ****************************************************************************/
6760
6761 void reply_printclose(struct smb_request *req)
6762 {
6763         connection_struct *conn = req->conn;
6764         files_struct *fsp;
6765         NTSTATUS status;
6766
6767         START_PROFILE(SMBsplclose);
6768
6769         if (req->wct < 1) {
6770                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6771                 END_PROFILE(SMBsplclose);
6772                 return;
6773         }
6774
6775         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6776
6777         if (!check_fsp(conn, req, fsp)) {
6778                 END_PROFILE(SMBsplclose);
6779                 return;
6780         }
6781
6782         if (!CAN_PRINT(conn)) {
6783                 reply_force_doserror(req, ERRSRV, ERRerror);
6784                 END_PROFILE(SMBsplclose);
6785                 return;
6786         }
6787
6788         DEBUG(3,("printclose fd=%d %s\n",
6789                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6790
6791         status = close_file(req, fsp, NORMAL_CLOSE);
6792
6793         if(!NT_STATUS_IS_OK(status)) {
6794                 reply_nterror(req, status);
6795                 END_PROFILE(SMBsplclose);
6796                 return;
6797         }
6798
6799         reply_outbuf(req, 0, 0);
6800
6801         END_PROFILE(SMBsplclose);
6802         return;
6803 }
6804
6805 /****************************************************************************
6806  Reply to a printqueue.
6807 ****************************************************************************/
6808
6809 void reply_printqueue(struct smb_request *req)
6810 {
6811         const struct loadparm_substitution *lp_sub =
6812                 loadparm_s3_global_substitution();
6813         connection_struct *conn = req->conn;
6814         int max_count;
6815         int start_index;
6816
6817         START_PROFILE(SMBsplretq);
6818
6819         if (req->wct < 2) {
6820                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6821                 END_PROFILE(SMBsplretq);
6822                 return;
6823         }
6824
6825         max_count = SVAL(req->vwv+0, 0);
6826         start_index = SVAL(req->vwv+1, 0);
6827
6828         /* we used to allow the client to get the cnum wrong, but that
6829            is really quite gross and only worked when there was only
6830            one printer - I think we should now only accept it if they
6831            get it right (tridge) */
6832         if (!CAN_PRINT(conn)) {
6833                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6834                 END_PROFILE(SMBsplretq);
6835                 return;
6836         }
6837
6838         reply_outbuf(req, 2, 3);
6839         SSVAL(req->outbuf,smb_vwv0,0);
6840         SSVAL(req->outbuf,smb_vwv1,0);
6841         SCVAL(smb_buf(req->outbuf),0,1);
6842         SSVAL(smb_buf(req->outbuf),1,0);
6843
6844         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6845                  start_index, max_count));
6846
6847         {
6848                 TALLOC_CTX *mem_ctx = talloc_tos();
6849                 NTSTATUS status;
6850                 WERROR werr;
6851                 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6852                 struct rpc_pipe_client *cli = NULL;
6853                 struct dcerpc_binding_handle *b = NULL;
6854                 struct policy_handle handle;
6855                 struct spoolss_DevmodeContainer devmode_ctr;
6856                 union spoolss_JobInfo *info;
6857                 uint32_t count;
6858                 uint32_t num_to_get;
6859                 uint32_t first;
6860                 uint32_t i;
6861
6862                 ZERO_STRUCT(handle);
6863
6864                 status = rpc_pipe_open_interface(mem_ctx,
6865                                                  &ndr_table_spoolss,
6866                                                  conn->session_info,
6867                                                  conn->sconn->remote_address,
6868                                                  conn->sconn->local_address,
6869                                                  conn->sconn->msg_ctx,
6870                                                  &cli);
6871                 if (!NT_STATUS_IS_OK(status)) {
6872                         DEBUG(0, ("reply_printqueue: "
6873                                   "could not connect to spoolss: %s\n",
6874                                   nt_errstr(status)));
6875                         reply_nterror(req, status);
6876                         goto out;
6877                 }
6878                 b = cli->binding_handle;
6879
6880                 ZERO_STRUCT(devmode_ctr);
6881
6882                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6883                                                 sharename,
6884                                                 NULL, devmode_ctr,
6885                                                 SEC_FLAG_MAXIMUM_ALLOWED,
6886                                                 &handle,
6887                                                 &werr);
6888                 if (!NT_STATUS_IS_OK(status)) {
6889                         reply_nterror(req, status);
6890                         goto out;
6891                 }
6892                 if (!W_ERROR_IS_OK(werr)) {
6893                         reply_nterror(req, werror_to_ntstatus(werr));
6894                         goto out;
6895                 }
6896
6897                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6898                                                &handle,
6899                                                0, /* firstjob */
6900                                                0xff, /* numjobs */
6901                                                2, /* level */
6902                                                0, /* offered */
6903                                                &count,
6904                                                &info);
6905                 if (!W_ERROR_IS_OK(werr)) {
6906                         reply_nterror(req, werror_to_ntstatus(werr));
6907                         goto out;
6908                 }
6909
6910                 if (max_count > 0) {
6911                         first = start_index;
6912                 } else {
6913                         first = start_index + max_count + 1;
6914                 }
6915
6916                 if (first >= count) {
6917                         num_to_get = first;
6918                 } else {
6919                         num_to_get = first + MIN(ABS(max_count), count - first);
6920                 }
6921
6922                 for (i = first; i < num_to_get; i++) {
6923                         char blob[28];
6924                         char *p = blob;
6925                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6926                         int qstatus;
6927                         size_t len = 0;
6928                         uint16_t qrapjobid = pjobid_to_rap(sharename,
6929                                                         info[i].info2.job_id);
6930
6931                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
6932                                 qstatus = 2;
6933                         } else {
6934                                 qstatus = 3;
6935                         }
6936
6937                         srv_put_dos_date2(p, 0, qtime);
6938                         SCVAL(p, 4, qstatus);
6939                         SSVAL(p, 5, qrapjobid);
6940                         SIVAL(p, 7, info[i].info2.size);
6941                         SCVAL(p, 11, 0);
6942                         status = srvstr_push(blob, req->flags2, p+12,
6943                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
6944                         if (!NT_STATUS_IS_OK(status)) {
6945                                 reply_nterror(req, status);
6946                                 goto out;
6947                         }
6948                         if (message_push_blob(
6949                                     &req->outbuf,
6950                                     data_blob_const(
6951                                             blob, sizeof(blob))) == -1) {
6952                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6953                                 goto out;
6954                         }
6955                 }
6956
6957                 if (count > 0) {
6958                         SSVAL(req->outbuf,smb_vwv0,count);
6959                         SSVAL(req->outbuf,smb_vwv1,
6960                               (max_count>0?first+count:first-1));
6961                         SCVAL(smb_buf(req->outbuf),0,1);
6962                         SSVAL(smb_buf(req->outbuf),1,28*count);
6963                 }
6964
6965
6966                 DEBUG(3, ("%u entries returned in queue\n",
6967                           (unsigned)count));
6968
6969 out:
6970                 if (b && is_valid_policy_hnd(&handle)) {
6971                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6972                 }
6973
6974         }
6975
6976         END_PROFILE(SMBsplretq);
6977         return;
6978 }
6979
6980 /****************************************************************************
6981  Reply to a printwrite.
6982 ****************************************************************************/
6983
6984 void reply_printwrite(struct smb_request *req)
6985 {
6986         connection_struct *conn = req->conn;
6987         int numtowrite;
6988         const char *data;
6989         files_struct *fsp;
6990
6991         START_PROFILE(SMBsplwr);
6992
6993         if (req->wct < 1) {
6994                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6995                 END_PROFILE(SMBsplwr);
6996                 return;
6997         }
6998
6999         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7000
7001         if (!check_fsp(conn, req, fsp)) {
7002                 END_PROFILE(SMBsplwr);
7003                 return;
7004         }
7005
7006         if (!fsp->print_file) {
7007                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7008                 END_PROFILE(SMBsplwr);
7009                 return;
7010         }
7011
7012         if (!CHECK_WRITE(fsp)) {
7013                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7014                 END_PROFILE(SMBsplwr);
7015                 return;
7016         }
7017
7018         numtowrite = SVAL(req->buf, 1);
7019
7020         /*
7021          * This already protects us against CVE-2017-12163.
7022          */
7023         if (req->buflen < numtowrite + 3) {
7024                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7025                 END_PROFILE(SMBsplwr);
7026                 return;
7027         }
7028
7029         data = (const char *)req->buf + 3;
7030
7031         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7032                 reply_nterror(req, map_nt_error_from_unix(errno));
7033                 END_PROFILE(SMBsplwr);
7034                 return;
7035         }
7036
7037         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7038
7039         END_PROFILE(SMBsplwr);
7040         return;
7041 }
7042
7043 /****************************************************************************
7044  Reply to a mkdir.
7045 ****************************************************************************/
7046
7047 void reply_mkdir(struct smb_request *req)
7048 {
7049         connection_struct *conn = req->conn;
7050         struct smb_filename *smb_dname = NULL;
7051         char *directory = NULL;
7052         NTSTATUS status;
7053         uint32_t ucf_flags;
7054         TALLOC_CTX *ctx = talloc_tos();
7055
7056         START_PROFILE(SMBmkdir);
7057
7058         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7059                             STR_TERMINATE, &status);
7060         if (!NT_STATUS_IS_OK(status)) {
7061                 reply_nterror(req, status);
7062                 goto out;
7063         }
7064
7065         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7066         status = filename_convert(ctx, conn,
7067                                  directory,
7068                                  ucf_flags,
7069                                  0,
7070                                  &smb_dname);
7071         if (!NT_STATUS_IS_OK(status)) {
7072                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7073                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7074                                         ERRSRV, ERRbadpath);
7075                         goto out;
7076                 }
7077                 reply_nterror(req, status);
7078                 goto out;
7079         }
7080
7081         status = create_directory(conn, req, smb_dname);
7082
7083         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7084
7085         if (!NT_STATUS_IS_OK(status)) {
7086
7087                 if (!use_nt_status()
7088                     && NT_STATUS_EQUAL(status,
7089                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
7090                         /*
7091                          * Yes, in the DOS error code case we get a
7092                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7093                          * samba4 torture test.
7094                          */
7095                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7096                 }
7097
7098                 reply_nterror(req, status);
7099                 goto out;
7100         }
7101
7102         reply_outbuf(req, 0, 0);
7103
7104         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7105  out:
7106         TALLOC_FREE(smb_dname);
7107         END_PROFILE(SMBmkdir);
7108         return;
7109 }
7110
7111 /****************************************************************************
7112  Reply to a rmdir.
7113 ****************************************************************************/
7114
7115 void reply_rmdir(struct smb_request *req)
7116 {
7117         connection_struct *conn = req->conn;
7118         struct smb_filename *smb_dname = NULL;
7119         char *directory = NULL;
7120         NTSTATUS status;
7121         TALLOC_CTX *ctx = talloc_tos();
7122         files_struct *fsp = NULL;
7123         int info = 0;
7124         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7125
7126         START_PROFILE(SMBrmdir);
7127
7128         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7129                             STR_TERMINATE, &status);
7130         if (!NT_STATUS_IS_OK(status)) {
7131                 reply_nterror(req, status);
7132                 goto out;
7133         }
7134
7135         status = filename_convert(ctx, conn,
7136                                  directory,
7137                                  ucf_flags,
7138                                  0,
7139                                  &smb_dname);
7140         if (!NT_STATUS_IS_OK(status)) {
7141                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7142                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7143                                         ERRSRV, ERRbadpath);
7144                         goto out;
7145                 }
7146                 reply_nterror(req, status);
7147                 goto out;
7148         }
7149
7150         if (is_ntfs_stream_smb_fname(smb_dname)) {
7151                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7152                 goto out;
7153         }
7154
7155         status = SMB_VFS_CREATE_FILE(
7156                 conn,                                   /* conn */
7157                 req,                                    /* req */
7158                 smb_dname,                              /* fname */
7159                 DELETE_ACCESS,                          /* access_mask */
7160                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7161                         FILE_SHARE_DELETE),
7162                 FILE_OPEN,                              /* create_disposition*/
7163                 FILE_DIRECTORY_FILE,                    /* create_options */
7164                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
7165                 0,                                      /* oplock_request */
7166                 NULL,                                   /* lease */
7167                 0,                                      /* allocation_size */
7168                 0,                                      /* private_flags */
7169                 NULL,                                   /* sd */
7170                 NULL,                                   /* ea_list */
7171                 &fsp,                                   /* result */
7172                 &info,                                  /* pinfo */
7173                 NULL, NULL);                            /* create context */
7174
7175         if (!NT_STATUS_IS_OK(status)) {
7176                 if (open_was_deferred(req->xconn, req->mid)) {
7177                         /* We have re-scheduled this call. */
7178                         goto out;
7179                 }
7180                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7181                         bool ok = defer_smb1_sharing_violation(req);
7182                         if (ok) {
7183                                 goto out;
7184                         }
7185                 }
7186                 reply_nterror(req, status);
7187                 goto out;
7188         }
7189
7190         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7191         if (!NT_STATUS_IS_OK(status)) {
7192                 close_file(req, fsp, ERROR_CLOSE);
7193                 reply_nterror(req, status);
7194                 goto out;
7195         }
7196
7197         if (!set_delete_on_close(fsp, true,
7198                         conn->session_info->security_token,
7199                         conn->session_info->unix_token)) {
7200                 close_file(req, fsp, ERROR_CLOSE);
7201                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7202                 goto out;
7203         }
7204
7205         status = close_file(req, fsp, NORMAL_CLOSE);
7206         if (!NT_STATUS_IS_OK(status)) {
7207                 reply_nterror(req, status);
7208         } else {
7209                 reply_outbuf(req, 0, 0);
7210         }
7211
7212         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7213  out:
7214         TALLOC_FREE(smb_dname);
7215         END_PROFILE(SMBrmdir);
7216         return;
7217 }
7218
7219 /*******************************************************************
7220  Resolve wildcards in a filename rename.
7221 ********************************************************************/
7222
7223 static bool resolve_wildcards(TALLOC_CTX *ctx,
7224                                 const char *name1,
7225                                 const char *name2,
7226                                 char **pp_newname)
7227 {
7228         char *name2_copy = NULL;
7229         char *root1 = NULL;
7230         char *root2 = NULL;
7231         char *ext1 = NULL;
7232         char *ext2 = NULL;
7233         char *p,*p2, *pname1, *pname2;
7234
7235         name2_copy = talloc_strdup(ctx, name2);
7236         if (!name2_copy) {
7237                 return False;
7238         }
7239
7240         pname1 = strrchr_m(name1,'/');
7241         pname2 = strrchr_m(name2_copy,'/');
7242
7243         if (!pname1 || !pname2) {
7244                 return False;
7245         }
7246
7247         /* Truncate the copy of name2 at the last '/' */
7248         *pname2 = '\0';
7249
7250         /* Now go past the '/' */
7251         pname1++;
7252         pname2++;
7253
7254         root1 = talloc_strdup(ctx, pname1);
7255         root2 = talloc_strdup(ctx, pname2);
7256
7257         if (!root1 || !root2) {
7258                 return False;
7259         }
7260
7261         p = strrchr_m(root1,'.');
7262         if (p) {
7263                 *p = 0;
7264                 ext1 = talloc_strdup(ctx, p+1);
7265         } else {
7266                 ext1 = talloc_strdup(ctx, "");
7267         }
7268         p = strrchr_m(root2,'.');
7269         if (p) {
7270                 *p = 0;
7271                 ext2 = talloc_strdup(ctx, p+1);
7272         } else {
7273                 ext2 = talloc_strdup(ctx, "");
7274         }
7275
7276         if (!ext1 || !ext2) {
7277                 return False;
7278         }
7279
7280         p = root1;
7281         p2 = root2;
7282         while (*p2) {
7283                 if (*p2 == '?') {
7284                         /* Hmmm. Should this be mb-aware ? */
7285                         *p2 = *p;
7286                         p2++;
7287                 } else if (*p2 == '*') {
7288                         *p2 = '\0';
7289                         root2 = talloc_asprintf(ctx, "%s%s",
7290                                                 root2,
7291                                                 p);
7292                         if (!root2) {
7293                                 return False;
7294                         }
7295                         break;
7296                 } else {
7297                         p2++;
7298                 }
7299                 if (*p) {
7300                         p++;
7301                 }
7302         }
7303
7304         p = ext1;
7305         p2 = ext2;
7306         while (*p2) {
7307                 if (*p2 == '?') {
7308                         /* Hmmm. Should this be mb-aware ? */
7309                         *p2 = *p;
7310                         p2++;
7311                 } else if (*p2 == '*') {
7312                         *p2 = '\0';
7313                         ext2 = talloc_asprintf(ctx, "%s%s",
7314                                                 ext2,
7315                                                 p);
7316                         if (!ext2) {
7317                                 return False;
7318                         }
7319                         break;
7320                 } else {
7321                         p2++;
7322                 }
7323                 if (*p) {
7324                         p++;
7325                 }
7326         }
7327
7328         if (*ext2) {
7329                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7330                                 name2_copy,
7331                                 root2,
7332                                 ext2);
7333         } else {
7334                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7335                                 name2_copy,
7336                                 root2);
7337         }
7338
7339         if (!*pp_newname) {
7340                 return False;
7341         }
7342
7343         return True;
7344 }
7345
7346 /****************************************************************************
7347  Ensure open files have their names updated. Updated to notify other smbd's
7348  asynchronously.
7349 ****************************************************************************/
7350
7351 static void rename_open_files(connection_struct *conn,
7352                               struct share_mode_lock *lck,
7353                               struct file_id id,
7354                               uint32_t orig_name_hash,
7355                               const struct smb_filename *smb_fname_dst)
7356 {
7357         files_struct *fsp;
7358         bool did_rename = False;
7359         NTSTATUS status;
7360         uint32_t new_name_hash = 0;
7361
7362         for(fsp = file_find_di_first(conn->sconn, id); fsp;
7363             fsp = file_find_di_next(fsp)) {
7364                 struct file_id_buf idbuf;
7365                 /* fsp_name is a relative path under the fsp. To change this for other
7366                    sharepaths we need to manipulate relative paths. */
7367                 /* TODO - create the absolute path and manipulate the newname
7368                    relative to the sharepath. */
7369                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7370                         continue;
7371                 }
7372                 if (fsp->name_hash != orig_name_hash) {
7373                         continue;
7374                 }
7375                 DBG_DEBUG("renaming file %s "
7376                           "(file_id %s) from %s -> %s\n",
7377                           fsp_fnum_dbg(fsp),
7378                           file_id_str_buf(fsp->file_id, &idbuf),
7379                           fsp_str_dbg(fsp),
7380                           smb_fname_str_dbg(smb_fname_dst));
7381
7382                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7383                 if (NT_STATUS_IS_OK(status)) {
7384                         did_rename = True;
7385                         new_name_hash = fsp->name_hash;
7386                 }
7387         }
7388
7389         if (!did_rename) {
7390                 struct file_id_buf idbuf;
7391                 DBG_DEBUG("no open files on file_id %s "
7392                           "for %s\n",
7393                           file_id_str_buf(id, &idbuf),
7394                           smb_fname_str_dbg(smb_fname_dst));
7395         }
7396
7397         /* Send messages to all smbd's (not ourself) that the name has changed. */
7398         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7399                               orig_name_hash, new_name_hash,
7400                               smb_fname_dst);
7401
7402 }
7403
7404 /****************************************************************************
7405  We need to check if the source path is a parent directory of the destination
7406  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7407  refuse the rename with a sharing violation. Under UNIX the above call can
7408  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7409  probably need to check that the client is a Windows one before disallowing
7410  this as a UNIX client (one with UNIX extensions) can know the source is a
7411  symlink and make this decision intelligently. Found by an excellent bug
7412  report from <AndyLiebman@aol.com>.
7413 ****************************************************************************/
7414
7415 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7416                                      const struct smb_filename *smb_fname_dst)
7417 {
7418         const char *psrc = smb_fname_src->base_name;
7419         const char *pdst = smb_fname_dst->base_name;
7420         size_t slen;
7421
7422         if (psrc[0] == '.' && psrc[1] == '/') {
7423                 psrc += 2;
7424         }
7425         if (pdst[0] == '.' && pdst[1] == '/') {
7426                 pdst += 2;
7427         }
7428         if ((slen = strlen(psrc)) > strlen(pdst)) {
7429                 return False;
7430         }
7431         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7432 }
7433
7434 /*
7435  * Do the notify calls from a rename
7436  */
7437
7438 static void notify_rename(connection_struct *conn, bool is_dir,
7439                           const struct smb_filename *smb_fname_src,
7440                           const struct smb_filename *smb_fname_dst)
7441 {
7442         char *parent_dir_src = NULL;
7443         char *parent_dir_dst = NULL;
7444         uint32_t mask;
7445
7446         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7447                 : FILE_NOTIFY_CHANGE_FILE_NAME;
7448
7449         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7450                             &parent_dir_src, NULL) ||
7451             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7452                             &parent_dir_dst, NULL)) {
7453                 goto out;
7454         }
7455
7456         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7457                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7458                              smb_fname_src->base_name);
7459                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7460                              smb_fname_dst->base_name);
7461         }
7462         else {
7463                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7464                              smb_fname_src->base_name);
7465                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7466                              smb_fname_dst->base_name);
7467         }
7468
7469         /* this is a strange one. w2k3 gives an additional event for
7470            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7471            files, but not directories */
7472         if (!is_dir) {
7473                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7474                              FILE_NOTIFY_CHANGE_ATTRIBUTES
7475                              |FILE_NOTIFY_CHANGE_CREATION,
7476                              smb_fname_dst->base_name);
7477         }
7478  out:
7479         TALLOC_FREE(parent_dir_src);
7480         TALLOC_FREE(parent_dir_dst);
7481 }
7482
7483 /****************************************************************************
7484  Returns an error if the parent directory for a filename is open in an
7485  incompatible way.
7486 ****************************************************************************/
7487
7488 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7489                                         const struct smb_filename *smb_fname_dst_in)
7490 {
7491         struct smb_filename *smb_fname_parent = NULL;
7492         struct file_id id;
7493         files_struct *fsp = NULL;
7494         int ret;
7495         bool ok;
7496
7497         ok = parent_smb_fname(talloc_tos(),
7498                               smb_fname_dst_in,
7499                               &smb_fname_parent,
7500                               NULL);
7501         if (!ok) {
7502                 return NT_STATUS_NO_MEMORY;
7503         }
7504
7505         ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7506         if (ret == -1) {
7507                 return map_nt_error_from_unix(errno);
7508         }
7509
7510         /*
7511          * We're only checking on this smbd here, mostly good
7512          * enough.. and will pass tests.
7513          */
7514
7515         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7516         for (fsp = file_find_di_first(conn->sconn, id); fsp;
7517                         fsp = file_find_di_next(fsp)) {
7518                 if (fsp->access_mask & DELETE_ACCESS) {
7519                         return NT_STATUS_SHARING_VIOLATION;
7520                 }
7521         }
7522         return NT_STATUS_OK;
7523 }
7524
7525 /****************************************************************************
7526  Rename an open file - given an fsp.
7527 ****************************************************************************/
7528
7529 NTSTATUS rename_internals_fsp(connection_struct *conn,
7530                         files_struct *fsp,
7531                         const struct smb_filename *smb_fname_dst_in,
7532                         const char *dst_original_lcomp,
7533                         uint32_t attrs,
7534                         bool replace_if_exists)
7535 {
7536         TALLOC_CTX *ctx = talloc_tos();
7537         struct smb_filename *smb_fname_dst = NULL;
7538         NTSTATUS status = NT_STATUS_OK;
7539         struct share_mode_lock *lck = NULL;
7540         uint32_t access_mask = SEC_DIR_ADD_FILE;
7541         bool dst_exists, old_is_stream, new_is_stream;
7542         int ret;
7543
7544         status = check_name(conn, smb_fname_dst_in);
7545         if (!NT_STATUS_IS_OK(status)) {
7546                 return status;
7547         }
7548
7549         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7550         if (!NT_STATUS_IS_OK(status)) {
7551                 return status;
7552         }
7553
7554         if (file_has_open_streams(fsp)) {
7555                 return NT_STATUS_ACCESS_DENIED;
7556         }
7557
7558         /* Make a copy of the dst smb_fname structs */
7559
7560         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7561         if (smb_fname_dst == NULL) {
7562                 status = NT_STATUS_NO_MEMORY;
7563                 goto out;
7564         }
7565
7566         /*
7567          * Check for special case with case preserving and not
7568          * case sensitive. If the new last component differs from the original
7569          * last component only by case, then we should allow
7570          * the rename (user is trying to change the case of the
7571          * filename).
7572          */
7573         if (!conn->case_sensitive && conn->case_preserve &&
7574             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7575             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7576                 char *fname_dst_parent = NULL;
7577                 const char *fname_dst_lcomp = NULL;
7578                 char *orig_lcomp_path = NULL;
7579                 char *orig_lcomp_stream = NULL;
7580                 bool ok = true;
7581
7582                 /*
7583                  * Split off the last component of the processed
7584                  * destination name. We will compare this to
7585                  * the split components of dst_original_lcomp.
7586                  */
7587                 if (!parent_dirname(ctx,
7588                                 smb_fname_dst->base_name,
7589                                 &fname_dst_parent,
7590                                 &fname_dst_lcomp)) {
7591                         status = NT_STATUS_NO_MEMORY;
7592                         goto out;
7593                 }
7594
7595                 /*
7596                  * The dst_original_lcomp component contains
7597                  * the last_component of the path + stream
7598                  * name (if a stream exists).
7599                  *
7600                  * Split off the stream name so we
7601                  * can check them separately.
7602                  */
7603
7604                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7605                         /* POSIX - no stream component. */
7606                         orig_lcomp_path = talloc_strdup(ctx,
7607                                                 dst_original_lcomp);
7608                         if (orig_lcomp_path == NULL) {
7609                                 ok = false;
7610                         }
7611                 } else {
7612                         ok = split_stream_filename(ctx,
7613                                         dst_original_lcomp,
7614                                         &orig_lcomp_path,
7615                                         &orig_lcomp_stream);
7616                 }
7617
7618                 if (!ok) {
7619                         TALLOC_FREE(fname_dst_parent);
7620                         status = NT_STATUS_NO_MEMORY;
7621                         goto out;
7622                 }
7623
7624                 /* If the base names only differ by case, use original. */
7625                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7626                         char *tmp;
7627                         /*
7628                          * Replace the modified last component with the
7629                          * original.
7630                          */
7631                         if (!ISDOT(fname_dst_parent)) {
7632                                 tmp = talloc_asprintf(smb_fname_dst,
7633                                         "%s/%s",
7634                                         fname_dst_parent,
7635                                         orig_lcomp_path);
7636                         } else {
7637                                 tmp = talloc_strdup(smb_fname_dst,
7638                                         orig_lcomp_path);
7639                         }
7640                         if (tmp == NULL) {
7641                                 status = NT_STATUS_NO_MEMORY;
7642                                 TALLOC_FREE(fname_dst_parent);
7643                                 TALLOC_FREE(orig_lcomp_path);
7644                                 TALLOC_FREE(orig_lcomp_stream);
7645                                 goto out;
7646                         }
7647                         TALLOC_FREE(smb_fname_dst->base_name);
7648                         smb_fname_dst->base_name = tmp;
7649                 }
7650
7651                 /* If the stream_names only differ by case, use original. */
7652                 if(!strcsequal(smb_fname_dst->stream_name,
7653                                orig_lcomp_stream)) {
7654                         /* Use the original stream. */
7655                         char *tmp = talloc_strdup(smb_fname_dst,
7656                                             orig_lcomp_stream);
7657                         if (tmp == NULL) {
7658                                 status = NT_STATUS_NO_MEMORY;
7659                                 TALLOC_FREE(fname_dst_parent);
7660                                 TALLOC_FREE(orig_lcomp_path);
7661                                 TALLOC_FREE(orig_lcomp_stream);
7662                                 goto out;
7663                         }
7664                         TALLOC_FREE(smb_fname_dst->stream_name);
7665                         smb_fname_dst->stream_name = tmp;
7666                 }
7667                 TALLOC_FREE(fname_dst_parent);
7668                 TALLOC_FREE(orig_lcomp_path);
7669                 TALLOC_FREE(orig_lcomp_stream);
7670         }
7671
7672         /*
7673          * If the src and dest names are identical - including case,
7674          * don't do the rename, just return success.
7675          */
7676
7677         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7678             strcsequal(fsp->fsp_name->stream_name,
7679                        smb_fname_dst->stream_name)) {
7680                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7681                           "- returning success\n",
7682                           smb_fname_str_dbg(smb_fname_dst)));
7683                 status = NT_STATUS_OK;
7684                 goto out;
7685         }
7686
7687         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7688         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7689
7690         /* Return the correct error code if both names aren't streams. */
7691         if (!old_is_stream && new_is_stream) {
7692                 status = NT_STATUS_OBJECT_NAME_INVALID;
7693                 goto out;
7694         }
7695
7696         if (old_is_stream && !new_is_stream) {
7697                 status = NT_STATUS_INVALID_PARAMETER;
7698                 goto out;
7699         }
7700
7701         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7702
7703         if(!replace_if_exists && dst_exists) {
7704                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7705                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7706                           smb_fname_str_dbg(smb_fname_dst)));
7707                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7708                 goto out;
7709         }
7710
7711         if (dst_exists) {
7712                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7713                     &smb_fname_dst->st);
7714                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7715                                                            fileid);
7716                 /* The file can be open when renaming a stream */
7717                 if (dst_fsp && !new_is_stream) {
7718                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7719                         status = NT_STATUS_ACCESS_DENIED;
7720                         goto out;
7721                 }
7722         }
7723
7724         /* Ensure we have a valid stat struct for the source. */
7725         status = vfs_stat_fsp(fsp);
7726         if (!NT_STATUS_IS_OK(status)) {
7727                 goto out;
7728         }
7729
7730         status = can_rename(conn, fsp, attrs);
7731
7732         if (!NT_STATUS_IS_OK(status)) {
7733                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7734                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7735                           smb_fname_str_dbg(smb_fname_dst)));
7736                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7737                         status = NT_STATUS_ACCESS_DENIED;
7738                 goto out;
7739         }
7740
7741         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7742                 status = NT_STATUS_ACCESS_DENIED;
7743                 goto out;
7744         }
7745
7746         /* Do we have rights to move into the destination ? */
7747         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7748                 /* We're moving a directory. */
7749                 access_mask = SEC_DIR_ADD_SUBDIR;
7750         }
7751         status = check_parent_access(conn,
7752                                 conn->cwd_fsp,
7753                                 smb_fname_dst,
7754                                 access_mask);
7755         if (!NT_STATUS_IS_OK(status)) {
7756                 DBG_INFO("check_parent_access on "
7757                         "dst %s returned %s\n",
7758                         smb_fname_str_dbg(smb_fname_dst),
7759                         nt_errstr(status));
7760                 goto out;
7761         }
7762
7763         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7764
7765         /*
7766          * We have the file open ourselves, so not being able to get the
7767          * corresponding share mode lock is a fatal error.
7768          */
7769
7770         SMB_ASSERT(lck != NULL);
7771
7772         ret = SMB_VFS_RENAMEAT(conn,
7773                         conn->cwd_fsp,
7774                         fsp->fsp_name,
7775                         conn->cwd_fsp,
7776                         smb_fname_dst);
7777         if (ret == 0) {
7778                 uint32_t create_options = fsp->fh->private_options;
7779
7780                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7781                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7782                           smb_fname_str_dbg(smb_fname_dst)));
7783
7784                 if (!fsp->fsp_flags.is_directory &&
7785                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7786                     (lp_map_archive(SNUM(conn)) ||
7787                     lp_store_dos_attributes(SNUM(conn)))) {
7788                         /* We must set the archive bit on the newly
7789                            renamed file. */
7790                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7791                                 uint32_t old_dosmode = dos_mode(conn,
7792                                                         smb_fname_dst);
7793                                 file_set_dosmode(conn,
7794                                         smb_fname_dst,
7795                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7796                                         NULL,
7797                                         true);
7798                         }
7799                 }
7800
7801                 notify_rename(conn,
7802                               fsp->fsp_flags.is_directory,
7803                               fsp->fsp_name,
7804                               smb_fname_dst);
7805
7806                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7807                                   smb_fname_dst);
7808
7809                 /*
7810                  * A rename acts as a new file create w.r.t. allowing an initial delete
7811                  * on close, probably because in Windows there is a new handle to the
7812                  * new file. If initial delete on close was requested but not
7813                  * originally set, we need to set it here. This is probably not 100% correct,
7814                  * but will work for the CIFSFS client which in non-posix mode
7815                  * depends on these semantics. JRA.
7816                  */
7817
7818                 if (create_options & FILE_DELETE_ON_CLOSE) {
7819                         status = can_set_delete_on_close(fsp, 0);
7820
7821                         if (NT_STATUS_IS_OK(status)) {
7822                                 /* Note that here we set the *initial* delete on close flag,
7823                                  * not the regular one. The magic gets handled in close. */
7824                                 fsp->fsp_flags.initial_delete_on_close = true;
7825                         }
7826                 }
7827                 TALLOC_FREE(lck);
7828                 status = NT_STATUS_OK;
7829                 goto out;
7830         }
7831
7832         TALLOC_FREE(lck);
7833
7834         if (errno == ENOTDIR || errno == EISDIR) {
7835                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7836         } else {
7837                 status = map_nt_error_from_unix(errno);
7838         }
7839
7840         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7841                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7842                   smb_fname_str_dbg(smb_fname_dst)));
7843
7844  out:
7845         TALLOC_FREE(smb_fname_dst);
7846
7847         return status;
7848 }
7849
7850 /****************************************************************************
7851  The guts of the rename command, split out so it may be called by the NT SMB
7852  code.
7853 ****************************************************************************/
7854
7855 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7856                         connection_struct *conn,
7857                         struct smb_request *req,
7858                         struct smb_filename *smb_fname_src,
7859                         struct smb_filename *smb_fname_dst,
7860                         const char *dst_original_lcomp,
7861                         uint32_t attrs,
7862                         bool replace_if_exists,
7863                         uint32_t access_mask)
7864 {
7865         char *fname_src_dir = NULL;
7866         struct smb_filename *smb_fname_src_dir = NULL;
7867         char *fname_src_mask = NULL;
7868         int count=0;
7869         NTSTATUS status = NT_STATUS_OK;
7870         struct smb_Dir *dir_hnd = NULL;
7871         const char *dname = NULL;
7872         char *talloced = NULL;
7873         long offset = 0;
7874         int create_options = 0;
7875         bool posix_pathnames = (req != NULL && req->posix_pathnames);
7876         struct smb2_create_blobs *posx = NULL;
7877         int rc;
7878         bool src_has_wild = false;
7879         bool dest_has_wild = false;
7880
7881         /*
7882          * Split the old name into directory and last component
7883          * strings. Note that unix_convert may have stripped off a
7884          * leading ./ from both name and newname if the rename is
7885          * at the root of the share. We need to make sure either both
7886          * name and newname contain a / character or neither of them do
7887          * as this is checked in resolve_wildcards().
7888          */
7889
7890         /* Split up the directory from the filename/mask. */
7891         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7892                                       &fname_src_dir, &fname_src_mask);
7893         if (!NT_STATUS_IS_OK(status)) {
7894                 status = NT_STATUS_NO_MEMORY;
7895                 goto out;
7896         }
7897
7898         if (req != NULL && !req->posix_pathnames) {
7899                 /*
7900                  * Check the wildcard mask *before*
7901                  * unmangling. As mangling is done
7902                  * for names that can't be returned
7903                  * to Windows the unmangled name may
7904                  * contain Windows wildcard characters.
7905                  */
7906                 src_has_wild = ms_has_wild(fname_src_mask);
7907                 dest_has_wild = ms_has_wild(dst_original_lcomp);
7908         }
7909
7910         /*
7911          * We should only check the mangled cache
7912          * here if unix_convert failed. This means
7913          * that the path in 'mask' doesn't exist
7914          * on the file system and so we need to look
7915          * for a possible mangle. This patch from
7916          * Tine Smukavec <valentin.smukavec@hermes.si>.
7917          */
7918
7919         if (!VALID_STAT(smb_fname_src->st) &&
7920             mangle_is_mangled(fname_src_mask, conn->params)) {
7921                 char *new_mask = NULL;
7922                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7923                                             conn->params);
7924                 if (new_mask) {
7925                         TALLOC_FREE(fname_src_mask);
7926                         fname_src_mask = new_mask;
7927                 }
7928         }
7929
7930         if (posix_pathnames) {
7931                 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7932                 if (!NT_STATUS_IS_OK(status)) {
7933                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7934                                     nt_errstr(status));
7935                         goto out;
7936                 }
7937         }
7938
7939         if (!src_has_wild) {
7940                 files_struct *fsp;
7941
7942                 /*
7943                  * Only one file needs to be renamed. Append the mask back
7944                  * onto the directory.
7945                  */
7946                 TALLOC_FREE(smb_fname_src->base_name);
7947                 if (ISDOT(fname_src_dir)) {
7948                         /* Ensure we use canonical names on open. */
7949                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7950                                                         "%s",
7951                                                         fname_src_mask);
7952                 } else {
7953                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7954                                                         "%s/%s",
7955                                                         fname_src_dir,
7956                                                         fname_src_mask);
7957                 }
7958                 if (!smb_fname_src->base_name) {
7959                         status = NT_STATUS_NO_MEMORY;
7960                         goto out;
7961                 }
7962
7963                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7964                           "case_preserve = %d, short case preserve = %d, "
7965                           "directory = %s, newname = %s, "
7966                           "last_component_dest = %s\n",
7967                           conn->case_sensitive, conn->case_preserve,
7968                           conn->short_case_preserve,
7969                           smb_fname_str_dbg(smb_fname_src),
7970                           smb_fname_str_dbg(smb_fname_dst),
7971                           dst_original_lcomp));
7972
7973                 /* The dest name still may have wildcards. */
7974                 if (dest_has_wild) {
7975                         char *fname_dst_mod = NULL;
7976                         if (!resolve_wildcards(smb_fname_dst,
7977                                                smb_fname_src->base_name,
7978                                                smb_fname_dst->base_name,
7979                                                &fname_dst_mod)) {
7980                                 DEBUG(6, ("rename_internals: resolve_wildcards "
7981                                           "%s %s failed\n",
7982                                           smb_fname_src->base_name,
7983                                           smb_fname_dst->base_name));
7984                                 status = NT_STATUS_NO_MEMORY;
7985                                 goto out;
7986                         }
7987                         TALLOC_FREE(smb_fname_dst->base_name);
7988                         smb_fname_dst->base_name = fname_dst_mod;
7989                 }
7990
7991                 ZERO_STRUCT(smb_fname_src->st);
7992                 if (posix_pathnames) {
7993                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7994                 } else {
7995                         rc = SMB_VFS_STAT(conn, smb_fname_src);
7996                 }
7997                 if (rc == -1) {
7998                         status = map_nt_error_from_unix_common(errno);
7999                         goto out;
8000                 }
8001
8002                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8003                         create_options |= FILE_DIRECTORY_FILE;
8004                 }
8005
8006                 status = SMB_VFS_CREATE_FILE(
8007                         conn,                           /* conn */
8008                         req,                            /* req */
8009                         smb_fname_src,                  /* fname */
8010                         access_mask,                    /* access_mask */
8011                         (FILE_SHARE_READ |              /* share_access */
8012                             FILE_SHARE_WRITE),
8013                         FILE_OPEN,                      /* create_disposition*/
8014                         create_options,                 /* create_options */
8015                         0,                              /* file_attributes */
8016                         0,                              /* oplock_request */
8017                         NULL,                           /* lease */
8018                         0,                              /* allocation_size */
8019                         0,                              /* private_flags */
8020                         NULL,                           /* sd */
8021                         NULL,                           /* ea_list */
8022                         &fsp,                           /* result */
8023                         NULL,                           /* pinfo */
8024                         posx,                           /* in_context_blobs */
8025                         NULL);                          /* out_context_blobs */
8026
8027                 if (!NT_STATUS_IS_OK(status)) {
8028                         DEBUG(3, ("Could not open rename source %s: %s\n",
8029                                   smb_fname_str_dbg(smb_fname_src),
8030                                   nt_errstr(status)));
8031                         goto out;
8032                 }
8033
8034                 status = rename_internals_fsp(conn,
8035                                         fsp,
8036                                         smb_fname_dst,
8037                                         dst_original_lcomp,
8038                                         attrs,
8039                                         replace_if_exists);
8040
8041                 close_file(req, fsp, NORMAL_CLOSE);
8042
8043                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8044                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8045                           smb_fname_str_dbg(smb_fname_dst)));
8046
8047                 goto out;
8048         }
8049
8050         /*
8051          * Wildcards - process each file that matches.
8052          */
8053         if (strequal(fname_src_mask, "????????.???")) {
8054                 TALLOC_FREE(fname_src_mask);
8055                 fname_src_mask = talloc_strdup(ctx, "*");
8056                 if (!fname_src_mask) {
8057                         status = NT_STATUS_NO_MEMORY;
8058                         goto out;
8059                 }
8060         }
8061
8062         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8063                                 fname_src_dir,
8064                                 NULL,
8065                                 NULL,
8066                                 smb_fname_src->twrp,
8067                                 smb_fname_src->flags);
8068         if (smb_fname_src_dir == NULL) {
8069                 status = NT_STATUS_NO_MEMORY;
8070                 goto out;
8071         }
8072
8073         status = check_name(conn, smb_fname_src_dir);
8074         if (!NT_STATUS_IS_OK(status)) {
8075                 goto out;
8076         }
8077
8078         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8079                           attrs);
8080         if (dir_hnd == NULL) {
8081                 status = map_nt_error_from_unix(errno);
8082                 goto out;
8083         }
8084
8085         status = NT_STATUS_NO_SUCH_FILE;
8086         /*
8087          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8088          * - gentest fix. JRA
8089          */
8090
8091         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8092                                     &talloced))) {
8093                 files_struct *fsp = NULL;
8094                 char *destname = NULL;
8095                 bool sysdir_entry = False;
8096
8097                 /* Quick check for "." and ".." */
8098                 if (ISDOT(dname) || ISDOTDOT(dname)) {
8099                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8100                                 sysdir_entry = True;
8101                         } else {
8102                                 TALLOC_FREE(talloced);
8103                                 continue;
8104                         }
8105                 }
8106
8107                 if (!is_visible_file(conn,
8108                                 dir_hnd,
8109                                 dname,
8110                                 &smb_fname_src->st,
8111                                 false)) {
8112                         TALLOC_FREE(talloced);
8113                         continue;
8114                 }
8115
8116                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8117                         TALLOC_FREE(talloced);
8118                         continue;
8119                 }
8120
8121                 if (sysdir_entry) {
8122                         status = NT_STATUS_OBJECT_NAME_INVALID;
8123                         break;
8124                 }
8125
8126                 TALLOC_FREE(smb_fname_src->base_name);
8127                 if (ISDOT(fname_src_dir)) {
8128                         /* Ensure we use canonical names on open. */
8129                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8130                                                         "%s",
8131                                                         dname);
8132                 } else {
8133                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8134                                                         "%s/%s",
8135                                                         fname_src_dir,
8136                                                         dname);
8137                 }
8138                 if (!smb_fname_src->base_name) {
8139                         status = NT_STATUS_NO_MEMORY;
8140                         goto out;
8141                 }
8142
8143                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8144                                        smb_fname_dst->base_name,
8145                                        &destname)) {
8146                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
8147                                   smb_fname_src->base_name, destname));
8148                         TALLOC_FREE(talloced);
8149                         continue;
8150                 }
8151                 if (!destname) {
8152                         status = NT_STATUS_NO_MEMORY;
8153                         goto out;
8154                 }
8155
8156                 TALLOC_FREE(smb_fname_dst->base_name);
8157                 smb_fname_dst->base_name = destname;
8158
8159                 ZERO_STRUCT(smb_fname_src->st);
8160                 if (posix_pathnames) {
8161                         SMB_VFS_LSTAT(conn, smb_fname_src);
8162                 } else {
8163                         SMB_VFS_STAT(conn, smb_fname_src);
8164                 }
8165
8166                 create_options = 0;
8167
8168                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8169                         create_options |= FILE_DIRECTORY_FILE;
8170                 }
8171
8172                 status = SMB_VFS_CREATE_FILE(
8173                         conn,                           /* conn */
8174                         req,                            /* req */
8175                         smb_fname_src,                  /* fname */
8176                         access_mask,                    /* access_mask */
8177                         (FILE_SHARE_READ |              /* share_access */
8178                             FILE_SHARE_WRITE),
8179                         FILE_OPEN,                      /* create_disposition*/
8180                         create_options,                 /* create_options */
8181                         0,                              /* file_attributes */
8182                         0,                              /* oplock_request */
8183                         NULL,                           /* lease */
8184                         0,                              /* allocation_size */
8185                         0,                              /* private_flags */
8186                         NULL,                           /* sd */
8187                         NULL,                           /* ea_list */
8188                         &fsp,                           /* result */
8189                         NULL,                           /* pinfo */
8190                         posx,                           /* in_context_blobs */
8191                         NULL);                          /* out_context_blobs */
8192
8193                 if (!NT_STATUS_IS_OK(status)) {
8194                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8195                                  "returned %s rename %s -> %s\n",
8196                                  nt_errstr(status),
8197                                  smb_fname_str_dbg(smb_fname_src),
8198                                  smb_fname_str_dbg(smb_fname_dst)));
8199                         break;
8200                 }
8201
8202                 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8203                 if (dst_original_lcomp == NULL) {
8204                         status = NT_STATUS_NO_MEMORY;
8205                         goto out;
8206                 }
8207
8208                 status = rename_internals_fsp(conn,
8209                                         fsp,
8210                                         smb_fname_dst,
8211                                         dst_original_lcomp,
8212                                         attrs,
8213                                         replace_if_exists);
8214
8215                 close_file(req, fsp, NORMAL_CLOSE);
8216
8217                 if (!NT_STATUS_IS_OK(status)) {
8218                         DEBUG(3, ("rename_internals_fsp returned %s for "
8219                                   "rename %s -> %s\n", nt_errstr(status),
8220                                   smb_fname_str_dbg(smb_fname_src),
8221                                   smb_fname_str_dbg(smb_fname_dst)));
8222                         break;
8223                 }
8224
8225                 count++;
8226
8227                 DEBUG(3,("rename_internals: doing rename on %s -> "
8228                          "%s\n", smb_fname_str_dbg(smb_fname_src),
8229                          smb_fname_str_dbg(smb_fname_src)));
8230                 TALLOC_FREE(talloced);
8231         }
8232         TALLOC_FREE(dir_hnd);
8233
8234         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8235                 status = map_nt_error_from_unix(errno);
8236         }
8237
8238  out:
8239         TALLOC_FREE(posx);
8240         TALLOC_FREE(talloced);
8241         TALLOC_FREE(smb_fname_src_dir);
8242         TALLOC_FREE(fname_src_dir);
8243         TALLOC_FREE(fname_src_mask);
8244         return status;
8245 }
8246
8247 /****************************************************************************
8248  Reply to a mv.
8249 ****************************************************************************/
8250
8251 void reply_mv(struct smb_request *req)
8252 {
8253         connection_struct *conn = req->conn;
8254         char *name = NULL;
8255         char *newname = NULL;
8256         const char *p;
8257         uint32_t attrs;
8258         NTSTATUS status;
8259         TALLOC_CTX *ctx = talloc_tos();
8260         struct smb_filename *smb_fname_src = NULL;
8261         struct smb_filename *smb_fname_dst = NULL;
8262         const char *dst_original_lcomp = NULL;
8263         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8264                 (req->posix_pathnames ?
8265                         UCF_UNIX_NAME_LOOKUP :
8266                         UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8267         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8268                 (req->posix_pathnames ?
8269                         0 :
8270                         UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8271         bool stream_rename = false;
8272
8273         START_PROFILE(SMBmv);
8274
8275         if (req->wct < 1) {
8276                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8277                 goto out;
8278         }
8279
8280         attrs = SVAL(req->vwv+0, 0);
8281
8282         p = (const char *)req->buf + 1;
8283         p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8284                                        &status);
8285         if (!NT_STATUS_IS_OK(status)) {
8286                 reply_nterror(req, status);
8287                 goto out;
8288         }
8289         p++;
8290         p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8291                                        &status);
8292         if (!NT_STATUS_IS_OK(status)) {
8293                 reply_nterror(req, status);
8294                 goto out;
8295         }
8296
8297         if (!req->posix_pathnames) {
8298                 /* The newname must begin with a ':' if the
8299                    name contains a ':'. */
8300                 if (strchr_m(name, ':')) {
8301                         if (newname[0] != ':') {
8302                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8303                                 goto out;
8304                         }
8305                         stream_rename = true;
8306                 }
8307         }
8308
8309         status = filename_convert(ctx,
8310                                   conn,
8311                                   name,
8312                                   src_ucf_flags,
8313                                   0,
8314                                   &smb_fname_src);
8315
8316         if (!NT_STATUS_IS_OK(status)) {
8317                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8318                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8319                                         ERRSRV, ERRbadpath);
8320                         goto out;
8321                 }
8322                 reply_nterror(req, status);
8323                 goto out;
8324         }
8325
8326         status = filename_convert(ctx,
8327                                   conn,
8328                                   newname,
8329                                   dst_ucf_flags,
8330                                   0,
8331                                   &smb_fname_dst);
8332
8333         if (!NT_STATUS_IS_OK(status)) {
8334                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8335                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8336                                         ERRSRV, ERRbadpath);
8337                         goto out;
8338                 }
8339                 reply_nterror(req, status);
8340                 goto out;
8341         }
8342
8343         /* Get the last component of the destination for rename_internals(). */
8344         dst_original_lcomp = get_original_lcomp(ctx,
8345                                         conn,
8346                                         newname,
8347                                         dst_ucf_flags);
8348         if (dst_original_lcomp == NULL) {
8349                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8350                 goto out;
8351         }
8352
8353         if (stream_rename) {
8354                 /* smb_fname_dst->base_name must be the same as
8355                    smb_fname_src->base_name. */
8356                 TALLOC_FREE(smb_fname_dst->base_name);
8357                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8358                                                 smb_fname_src->base_name);
8359                 if (!smb_fname_dst->base_name) {
8360                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8361                         goto out;
8362                 }
8363         }
8364
8365         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8366                  smb_fname_str_dbg(smb_fname_dst)));
8367
8368         status = rename_internals(ctx,
8369                                 conn,
8370                                 req,
8371                                 smb_fname_src,
8372                                 smb_fname_dst,
8373                                 dst_original_lcomp,
8374                                 attrs,
8375                                 false,
8376                                 DELETE_ACCESS);
8377         if (!NT_STATUS_IS_OK(status)) {
8378                 if (open_was_deferred(req->xconn, req->mid)) {
8379                         /* We have re-scheduled this call. */
8380                         goto out;
8381                 }
8382                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8383                         bool ok = defer_smb1_sharing_violation(req);
8384                         if (ok) {
8385                                 goto out;
8386                         }
8387                 }
8388                 reply_nterror(req, status);
8389                 goto out;
8390         }
8391
8392         reply_outbuf(req, 0, 0);
8393  out:
8394         TALLOC_FREE(smb_fname_src);
8395         TALLOC_FREE(smb_fname_dst);
8396         END_PROFILE(SMBmv);
8397         return;
8398 }
8399
8400 /*******************************************************************
8401  Copy a file as part of a reply_copy.
8402 ******************************************************************/
8403
8404 /*
8405  * TODO: check error codes on all callers
8406  */
8407
8408 NTSTATUS copy_file(TALLOC_CTX *ctx,
8409                         connection_struct *conn,
8410                         struct smb_filename *smb_fname_src,
8411                         struct smb_filename *smb_fname_dst,
8412                         int ofun,
8413                         int count,
8414                         bool target_is_directory)
8415 {
8416         struct smb_filename *smb_fname_dst_tmp = NULL;
8417         off_t ret=-1;
8418         files_struct *fsp1,*fsp2;
8419         uint32_t dosattrs;
8420         uint32_t new_create_disposition;
8421         NTSTATUS status;
8422
8423
8424         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8425         if (smb_fname_dst_tmp == NULL) {
8426                 return NT_STATUS_NO_MEMORY;
8427         }
8428
8429         /*
8430          * If the target is a directory, extract the last component from the
8431          * src filename and append it to the dst filename
8432          */
8433         if (target_is_directory) {
8434                 const char *p;
8435
8436                 /* dest/target can't be a stream if it's a directory. */
8437                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8438
8439                 p = strrchr_m(smb_fname_src->base_name,'/');
8440                 if (p) {
8441                         p++;
8442                 } else {
8443                         p = smb_fname_src->base_name;
8444                 }
8445                 smb_fname_dst_tmp->base_name =
8446                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8447                                            p);
8448                 if (!smb_fname_dst_tmp->base_name) {
8449                         status = NT_STATUS_NO_MEMORY;
8450                         goto out;
8451                 }
8452         }
8453
8454         status = vfs_file_exist(conn, smb_fname_src);
8455         if (!NT_STATUS_IS_OK(status)) {
8456                 goto out;
8457         }
8458
8459         if (!target_is_directory && count) {
8460                 new_create_disposition = FILE_OPEN;
8461         } else {
8462                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8463                                                  0, ofun,
8464                                                  NULL, NULL,
8465                                                  &new_create_disposition,
8466                                                  NULL,
8467                                                  NULL)) {
8468                         status = NT_STATUS_INVALID_PARAMETER;
8469                         goto out;
8470                 }
8471         }
8472
8473         /* Open the src file for reading. */
8474         status = SMB_VFS_CREATE_FILE(
8475                 conn,                                   /* conn */
8476                 NULL,                                   /* req */
8477                 smb_fname_src,                          /* fname */
8478                 FILE_GENERIC_READ,                      /* access_mask */
8479                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8480                 FILE_OPEN,                              /* create_disposition*/
8481                 0,                                      /* create_options */
8482                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
8483                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8484                 NULL,                                   /* lease */
8485                 0,                                      /* allocation_size */
8486                 0,                                      /* private_flags */
8487                 NULL,                                   /* sd */
8488                 NULL,                                   /* ea_list */
8489                 &fsp1,                                  /* result */
8490                 NULL,                                   /* psbuf */
8491                 NULL, NULL);                            /* create context */
8492
8493         if (!NT_STATUS_IS_OK(status)) {
8494                 goto out;
8495         }
8496
8497         dosattrs = dos_mode(conn, smb_fname_src);
8498
8499         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8500                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8501         }
8502
8503         /* Open the dst file for writing. */
8504         status = SMB_VFS_CREATE_FILE(
8505                 conn,                                   /* conn */
8506                 NULL,                                   /* req */
8507                 smb_fname_dst,                          /* fname */
8508                 FILE_GENERIC_WRITE,                     /* access_mask */
8509                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
8510                 new_create_disposition,                 /* create_disposition*/
8511                 0,                                      /* create_options */
8512                 dosattrs,                               /* file_attributes */
8513                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
8514                 NULL,                                   /* lease */
8515                 0,                                      /* allocation_size */
8516                 0,                                      /* private_flags */
8517                 NULL,                                   /* sd */
8518                 NULL,                                   /* ea_list */
8519                 &fsp2,                                  /* result */
8520                 NULL,                                   /* psbuf */
8521                 NULL, NULL);                            /* create context */
8522
8523         if (!NT_STATUS_IS_OK(status)) {
8524                 close_file(NULL, fsp1, ERROR_CLOSE);
8525                 goto out;
8526         }
8527
8528         if (ofun & OPENX_FILE_EXISTS_OPEN) {
8529                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8530                 if (ret == -1) {
8531                         DEBUG(0, ("error - vfs lseek returned error %s\n",
8532                                 strerror(errno)));
8533                         status = map_nt_error_from_unix(errno);
8534                         close_file(NULL, fsp1, ERROR_CLOSE);
8535                         close_file(NULL, fsp2, ERROR_CLOSE);
8536                         goto out;
8537                 }
8538         }
8539
8540         /* Do the actual copy. */
8541         if (smb_fname_src->st.st_ex_size) {
8542                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8543         } else {
8544                 ret = 0;
8545         }
8546
8547         close_file(NULL, fsp1, NORMAL_CLOSE);
8548
8549         /* Ensure the modtime is set correctly on the destination file. */
8550         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8551
8552         /*
8553          * As we are opening fsp1 read-only we only expect
8554          * an error on close on fsp2 if we are out of space.
8555          * Thus we don't look at the error return from the
8556          * close of fsp1.
8557          */
8558         status = close_file(NULL, fsp2, NORMAL_CLOSE);
8559
8560         if (!NT_STATUS_IS_OK(status)) {
8561                 goto out;
8562         }
8563
8564         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8565                 status = NT_STATUS_DISK_FULL;
8566                 goto out;
8567         }
8568
8569         status = NT_STATUS_OK;
8570
8571  out:
8572         TALLOC_FREE(smb_fname_dst_tmp);
8573         return status;
8574 }
8575
8576 /****************************************************************************
8577  Reply to a file copy.
8578 ****************************************************************************/
8579
8580 void reply_copy(struct smb_request *req)
8581 {
8582         connection_struct *conn = req->conn;
8583         struct smb_filename *smb_fname_src = NULL;
8584         struct smb_filename *smb_fname_src_dir = NULL;
8585         struct smb_filename *smb_fname_dst = NULL;
8586         char *fname_src = NULL;
8587         char *fname_dst = NULL;
8588         char *fname_src_mask = NULL;
8589         char *fname_src_dir = NULL;
8590         const char *p;
8591         int count=0;
8592         int error = ERRnoaccess;
8593         int tid2;
8594         int ofun;
8595         int flags;
8596         bool target_is_directory=False;
8597         bool source_has_wild = False;
8598         bool dest_has_wild = False;
8599         NTSTATUS status;
8600         uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8601                 ucf_flags_from_smb_request(req);
8602         uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8603                 ucf_flags_from_smb_request(req);
8604         TALLOC_CTX *ctx = talloc_tos();
8605
8606         START_PROFILE(SMBcopy);
8607
8608         if (req->wct < 3) {
8609                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610                 goto out;
8611         }
8612
8613         tid2 = SVAL(req->vwv+0, 0);
8614         ofun = SVAL(req->vwv+1, 0);
8615         flags = SVAL(req->vwv+2, 0);
8616
8617         p = (const char *)req->buf;
8618         p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8619                                        &status);
8620         if (!NT_STATUS_IS_OK(status)) {
8621                 reply_nterror(req, status);
8622                 goto out;
8623         }
8624         p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8625                                        &status);
8626         if (!NT_STATUS_IS_OK(status)) {
8627                 reply_nterror(req, status);
8628                 goto out;
8629         }
8630
8631         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8632
8633         if (tid2 != conn->cnum) {
8634                 /* can't currently handle inter share copies XXXX */
8635                 DEBUG(3,("Rejecting inter-share copy\n"));
8636                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8637                 goto out;
8638         }
8639
8640         status = filename_convert(ctx, conn,
8641                                   fname_src,
8642                                   ucf_flags_src,
8643                                   0,
8644                                   &smb_fname_src);
8645         if (!NT_STATUS_IS_OK(status)) {
8646                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8647                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8648                                         ERRSRV, ERRbadpath);
8649                         goto out;
8650                 }
8651                 reply_nterror(req, status);
8652                 goto out;
8653         }
8654
8655         status = filename_convert(ctx, conn,
8656                                   fname_dst,
8657                                   ucf_flags_dst,
8658                                   0,
8659                                   &smb_fname_dst);
8660         if (!NT_STATUS_IS_OK(status)) {
8661                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8662                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8663                                         ERRSRV, ERRbadpath);
8664                         goto out;
8665                 }
8666                 reply_nterror(req, status);
8667                 goto out;
8668         }
8669
8670         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8671
8672         if ((flags&1) && target_is_directory) {
8673                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8674                 goto out;
8675         }
8676
8677         if ((flags&2) && !target_is_directory) {
8678                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8679                 goto out;
8680         }
8681
8682         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8683                 /* wants a tree copy! XXXX */
8684                 DEBUG(3,("Rejecting tree copy\n"));
8685                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686                 goto out;
8687         }
8688
8689         /* Split up the directory from the filename/mask. */
8690         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8691                                       &fname_src_dir, &fname_src_mask);
8692         if (!NT_STATUS_IS_OK(status)) {
8693                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8694                 goto out;
8695         }
8696
8697         if (!req->posix_pathnames) {
8698                 /*
8699                  * Check the wildcard mask *before*
8700                  * unmangling. As mangling is done
8701                  * for names that can't be returned
8702                  * to Windows the unmangled name may
8703                  * contain Windows wildcard characters.
8704                  */
8705                 source_has_wild = ms_has_wild(fname_src_mask);
8706                 dest_has_wild = ms_has_wild(smb_fname_dst->base_name);
8707         }
8708
8709         /*
8710          * We should only check the mangled cache
8711          * here if unix_convert failed. This means
8712          * that the path in 'mask' doesn't exist
8713          * on the file system and so we need to look
8714          * for a possible mangle. This patch from
8715          * Tine Smukavec <valentin.smukavec@hermes.si>.
8716          */
8717         if (!VALID_STAT(smb_fname_src->st) &&
8718             mangle_is_mangled(fname_src_mask, conn->params)) {
8719                 char *new_mask = NULL;
8720                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8721                                             &new_mask, conn->params);
8722
8723                 /* Use demangled name if one was successfully found. */
8724                 if (new_mask) {
8725                         TALLOC_FREE(fname_src_mask);
8726                         fname_src_mask = new_mask;
8727                 }
8728         }
8729
8730         if (!source_has_wild) {
8731
8732                 /*
8733                  * Only one file needs to be copied. Append the mask back onto
8734                  * the directory.
8735                  */
8736                 TALLOC_FREE(smb_fname_src->base_name);
8737                 if (ISDOT(fname_src_dir)) {
8738                         /* Ensure we use canonical names on open. */
8739                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8740                                                         "%s",
8741                                                         fname_src_mask);
8742                 } else {
8743                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8744                                                         "%s/%s",
8745                                                         fname_src_dir,
8746                                                         fname_src_mask);
8747                 }
8748                 if (!smb_fname_src->base_name) {
8749                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8750                         goto out;
8751                 }
8752
8753                 if (dest_has_wild) {
8754                         char *fname_dst_mod = NULL;
8755                         if (!resolve_wildcards(smb_fname_dst,
8756                                                smb_fname_src->base_name,
8757                                                smb_fname_dst->base_name,
8758                                                &fname_dst_mod)) {
8759                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8760                                 goto out;
8761                         }
8762                         TALLOC_FREE(smb_fname_dst->base_name);
8763                         smb_fname_dst->base_name = fname_dst_mod;
8764                 }
8765
8766                 status = check_name(conn, smb_fname_src);
8767                 if (!NT_STATUS_IS_OK(status)) {
8768                         reply_nterror(req, status);
8769                         goto out;
8770                 }
8771
8772                 status = check_name(conn, smb_fname_dst);
8773                 if (!NT_STATUS_IS_OK(status)) {
8774                         reply_nterror(req, status);
8775                         goto out;
8776                 }
8777
8778                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8779                                    ofun, count, target_is_directory);
8780
8781                 if(!NT_STATUS_IS_OK(status)) {
8782                         reply_nterror(req, status);
8783                         goto out;
8784                 } else {
8785                         count++;
8786                 }
8787         } else {
8788                 struct smb_Dir *dir_hnd = NULL;
8789                 const char *dname = NULL;
8790                 char *talloced = NULL;
8791                 long offset = 0;
8792
8793                 /*
8794                  * There is a wildcard that requires us to actually read the
8795                  * src dir and copy each file matching the mask to the dst.
8796                  * Right now streams won't be copied, but this could
8797                  * presumably be added with a nested loop for reach dir entry.
8798                  */
8799                 SMB_ASSERT(!smb_fname_src->stream_name);
8800                 SMB_ASSERT(!smb_fname_dst->stream_name);
8801
8802                 smb_fname_src->stream_name = NULL;
8803                 smb_fname_dst->stream_name = NULL;
8804
8805                 if (strequal(fname_src_mask,"????????.???")) {
8806                         TALLOC_FREE(fname_src_mask);
8807                         fname_src_mask = talloc_strdup(ctx, "*");
8808                         if (!fname_src_mask) {
8809                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8810                                 goto out;
8811                         }
8812                 }
8813
8814                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8815                                         fname_src_dir,
8816                                         NULL,
8817                                         NULL,
8818                                         smb_fname_src->twrp,
8819                                         smb_fname_src->flags);
8820                 if (smb_fname_src_dir == NULL) {
8821                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8822                         goto out;
8823                 }
8824
8825                 status = check_name(conn, smb_fname_src_dir);
8826                 if (!NT_STATUS_IS_OK(status)) {
8827                         reply_nterror(req, status);
8828                         goto out;
8829                 }
8830
8831                 dir_hnd = OpenDir(ctx,
8832                                 conn,
8833                                 smb_fname_src_dir,
8834                                 fname_src_mask,
8835                                 0);
8836                 if (dir_hnd == NULL) {
8837                         status = map_nt_error_from_unix(errno);
8838                         reply_nterror(req, status);
8839                         goto out;
8840                 }
8841
8842                 error = ERRbadfile;
8843
8844                 /* Iterate over the src dir copying each entry to the dst. */
8845                 while ((dname = ReadDirName(dir_hnd, &offset,
8846                                             &smb_fname_src->st, &talloced))) {
8847                         char *destname = NULL;
8848
8849                         if (ISDOT(dname) || ISDOTDOT(dname)) {
8850                                 TALLOC_FREE(talloced);
8851                                 continue;
8852                         }
8853
8854                         if (!is_visible_file(conn,
8855                                         dir_hnd,
8856                                         dname,
8857                                         &smb_fname_src->st,
8858                                         false)) {
8859                                 TALLOC_FREE(talloced);
8860                                 continue;
8861                         }
8862
8863                         if(!mask_match(dname, fname_src_mask,
8864                                        conn->case_sensitive)) {
8865                                 TALLOC_FREE(talloced);
8866                                 continue;
8867                         }
8868
8869                         error = ERRnoaccess;
8870
8871                         /* Get the src smb_fname struct setup. */
8872                         TALLOC_FREE(smb_fname_src->base_name);
8873                         if (ISDOT(fname_src_dir)) {
8874                                 /* Ensure we use canonical names on open. */
8875                                 smb_fname_src->base_name =
8876                                         talloc_asprintf(smb_fname_src, "%s",
8877                                                 dname);
8878                         } else {
8879                                 smb_fname_src->base_name =
8880                                         talloc_asprintf(smb_fname_src, "%s/%s",
8881                                                 fname_src_dir, dname);
8882                         }
8883
8884                         if (!smb_fname_src->base_name) {
8885                                 TALLOC_FREE(dir_hnd);
8886                                 TALLOC_FREE(talloced);
8887                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8888                                 goto out;
8889                         }
8890
8891                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8892                                                smb_fname_dst->base_name,
8893                                                &destname)) {
8894                                 TALLOC_FREE(talloced);
8895                                 continue;
8896                         }
8897                         if (!destname) {
8898                                 TALLOC_FREE(dir_hnd);
8899                                 TALLOC_FREE(talloced);
8900                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8901                                 goto out;
8902                         }
8903
8904                         TALLOC_FREE(smb_fname_dst->base_name);
8905                         smb_fname_dst->base_name = destname;
8906
8907                         status = check_name(conn, smb_fname_src);
8908                         if (!NT_STATUS_IS_OK(status)) {
8909                                 TALLOC_FREE(dir_hnd);
8910                                 TALLOC_FREE(talloced);
8911                                 reply_nterror(req, status);
8912                                 goto out;
8913                         }
8914
8915                         status = check_name(conn, smb_fname_dst);
8916                         if (!NT_STATUS_IS_OK(status)) {
8917                                 TALLOC_FREE(dir_hnd);
8918                                 TALLOC_FREE(talloced);
8919                                 reply_nterror(req, status);
8920                                 goto out;
8921                         }
8922
8923                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8924                                 smb_fname_src->base_name,
8925                                 smb_fname_dst->base_name));
8926
8927                         status = copy_file(ctx, conn, smb_fname_src,
8928                                            smb_fname_dst, ofun, count,
8929                                            target_is_directory);
8930                         if (NT_STATUS_IS_OK(status)) {
8931                                 count++;
8932                         }
8933
8934                         TALLOC_FREE(talloced);
8935                 }
8936                 TALLOC_FREE(dir_hnd);
8937         }
8938
8939         if (count == 0) {
8940                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8941                 goto out;
8942         }
8943
8944         reply_outbuf(req, 1, 0);
8945         SSVAL(req->outbuf,smb_vwv0,count);
8946  out:
8947         TALLOC_FREE(smb_fname_src);
8948         TALLOC_FREE(smb_fname_src_dir);
8949         TALLOC_FREE(smb_fname_dst);
8950         TALLOC_FREE(fname_src);
8951         TALLOC_FREE(fname_dst);
8952         TALLOC_FREE(fname_src_mask);
8953         TALLOC_FREE(fname_src_dir);
8954
8955         END_PROFILE(SMBcopy);
8956         return;
8957 }
8958
8959 #undef DBGC_CLASS
8960 #define DBGC_CLASS DBGC_LOCKING
8961
8962 /****************************************************************************
8963  Get a lock pid, dealing with large count requests.
8964 ****************************************************************************/
8965
8966 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8967                     bool large_file_format)
8968 {
8969         if(!large_file_format)
8970                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8971         else
8972                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8973 }
8974
8975 /****************************************************************************
8976  Get a lock count, dealing with large count requests.
8977 ****************************************************************************/
8978
8979 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8980                         bool large_file_format)
8981 {
8982         uint64_t count = 0;
8983
8984         if(!large_file_format) {
8985                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8986         } else {
8987                 /*
8988                  * No BVAL, this is reversed!
8989                  */
8990                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8991                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8992         }
8993
8994         return count;
8995 }
8996
8997 /****************************************************************************
8998  Get a lock offset, dealing with large offset requests.
8999 ****************************************************************************/
9000
9001 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9002                          bool large_file_format)
9003 {
9004         uint64_t offset = 0;
9005
9006         if(!large_file_format) {
9007                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9008         } else {
9009                 /*
9010                  * No BVAL, this is reversed!
9011                  */
9012                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9013                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9014         }
9015
9016         return offset;
9017 }
9018
9019 struct smbd_do_unlocking_state {
9020         struct files_struct *fsp;
9021         uint16_t num_ulocks;
9022         struct smbd_lock_element *ulocks;
9023         enum brl_flavour lock_flav;
9024         NTSTATUS status;
9025 };
9026
9027 static void smbd_do_unlocking_fn(
9028         const uint8_t *buf,
9029         size_t buflen,
9030         bool *pmodified_dependent,
9031         void *private_data)
9032 {
9033         struct smbd_do_unlocking_state *state = private_data;
9034         struct files_struct *fsp = state->fsp;
9035         enum brl_flavour lock_flav = state->lock_flav;
9036         uint16_t i;
9037
9038         for (i = 0; i < state->num_ulocks; i++) {
9039                 struct smbd_lock_element *e = &state->ulocks[i];
9040
9041                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9042                           "pid %"PRIu64", file %s\n",
9043                           e->offset,
9044                           e->count,
9045                           e->smblctx,
9046                           fsp_str_dbg(fsp));
9047
9048                 if (e->brltype != UNLOCK_LOCK) {
9049                         /* this can only happen with SMB2 */
9050                         state->status = NT_STATUS_INVALID_PARAMETER;
9051                         return;
9052                 }
9053
9054                 state->status = do_unlock(
9055                         fsp, e->smblctx, e->count, e->offset, lock_flav);
9056
9057                 DBG_DEBUG("do_unlock returned %s\n",
9058                           nt_errstr(state->status));
9059
9060                 if (!NT_STATUS_IS_OK(state->status)) {
9061                         return;
9062                 }
9063         }
9064
9065         *pmodified_dependent = true;
9066 }
9067
9068 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9069                            files_struct *fsp,
9070                            uint16_t num_ulocks,
9071                            struct smbd_lock_element *ulocks,
9072                            enum brl_flavour lock_flav)
9073 {
9074         struct smbd_do_unlocking_state state = {
9075                 .fsp = fsp,
9076                 .num_ulocks = num_ulocks,
9077                 .ulocks = ulocks,
9078                 .lock_flav = lock_flav,
9079         };
9080         NTSTATUS status;
9081
9082         DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9083
9084         status = share_mode_do_locked(
9085                 fsp->file_id, smbd_do_unlocking_fn, &state);
9086
9087         if (!NT_STATUS_IS_OK(status)) {
9088                 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9089                           nt_errstr(status));
9090                 return status;
9091         }
9092         if (!NT_STATUS_IS_OK(state.status)) {
9093                 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9094                           nt_errstr(status));
9095                 return state.status;
9096         }
9097
9098         return NT_STATUS_OK;
9099 }
9100
9101 /****************************************************************************
9102  Reply to a lockingX request.
9103 ****************************************************************************/
9104
9105 static void reply_lockingx_done(struct tevent_req *subreq);
9106
9107 void reply_lockingX(struct smb_request *req)
9108 {
9109         connection_struct *conn = req->conn;
9110         files_struct *fsp;
9111         unsigned char locktype;
9112         enum brl_type brltype;
9113         unsigned char oplocklevel;
9114         uint16_t num_ulocks;
9115         uint16_t num_locks;
9116         int32_t lock_timeout;
9117         uint16_t i;
9118         const uint8_t *data;
9119         bool large_file_format;
9120         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9121         struct smbd_lock_element *locks = NULL;
9122         struct tevent_req *subreq = NULL;
9123
9124         START_PROFILE(SMBlockingX);
9125
9126         if (req->wct < 8) {
9127                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9128                 END_PROFILE(SMBlockingX);
9129                 return;
9130         }
9131
9132         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9133         locktype = CVAL(req->vwv+3, 0);
9134         oplocklevel = CVAL(req->vwv+3, 1);
9135         num_ulocks = SVAL(req->vwv+6, 0);
9136         num_locks = SVAL(req->vwv+7, 0);
9137         lock_timeout = IVAL(req->vwv+4, 0);
9138         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9139
9140         if (!check_fsp(conn, req, fsp)) {
9141                 END_PROFILE(SMBlockingX);
9142                 return;
9143         }
9144
9145         data = req->buf;
9146
9147         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9148                 /* we don't support these - and CANCEL_LOCK makes w2k
9149                    and XP reboot so I don't really want to be
9150                    compatible! (tridge) */
9151                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9152                 END_PROFILE(SMBlockingX);
9153                 return;
9154         }
9155
9156         /* Check if this is an oplock break on a file
9157            we have granted an oplock on.
9158         */
9159         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9160                 /* Client can insist on breaking to none. */
9161                 bool break_to_none = (oplocklevel == 0);
9162                 bool result;
9163
9164                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9165                          "for %s\n", (unsigned int)oplocklevel,
9166                          fsp_fnum_dbg(fsp)));
9167
9168                 /*
9169                  * Make sure we have granted an exclusive or batch oplock on
9170                  * this file.
9171                  */
9172
9173                 if (fsp->oplock_type == 0) {
9174
9175                         /* The Samba4 nbench simulator doesn't understand
9176                            the difference between break to level2 and break
9177                            to none from level2 - it sends oplock break
9178                            replies in both cases. Don't keep logging an error
9179                            message here - just ignore it. JRA. */
9180
9181                         DEBUG(5,("reply_lockingX: Error : oplock break from "
9182                                  "client for %s (oplock=%d) and no "
9183                                  "oplock granted on this file (%s).\n",
9184                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
9185                                  fsp_str_dbg(fsp)));
9186
9187                         /* if this is a pure oplock break request then don't
9188                          * send a reply */
9189                         if (num_locks == 0 && num_ulocks == 0) {
9190                                 END_PROFILE(SMBlockingX);
9191                                 return;
9192                         }
9193
9194                         END_PROFILE(SMBlockingX);
9195                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9196                         return;
9197                 }
9198
9199                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9200                     (break_to_none)) {
9201                         result = remove_oplock(fsp);
9202                 } else {
9203                         result = downgrade_oplock(fsp);
9204                 }
9205
9206                 if (!result) {
9207                         DEBUG(0, ("reply_lockingX: error in removing "
9208                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
9209                         /* Hmmm. Is this panic justified? */
9210                         smb_panic("internal tdb error");
9211                 }
9212
9213                 /* if this is a pure oplock break request then don't send a
9214                  * reply */
9215                 if (num_locks == 0 && num_ulocks == 0) {
9216                         /* Sanity check - ensure a pure oplock break is not a
9217                            chained request. */
9218                         if (CVAL(req->vwv+0, 0) != 0xff) {
9219                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
9220                                          "break is a chained %d request !\n",
9221                                          (unsigned int)CVAL(req->vwv+0, 0)));
9222                         }
9223                         END_PROFILE(SMBlockingX);
9224                         return;
9225                 }
9226         }
9227
9228         if (req->buflen <
9229             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9230                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9231                 END_PROFILE(SMBlockingX);
9232                 return;
9233         }
9234
9235         if (num_ulocks != 0) {
9236                 struct smbd_lock_element *ulocks = NULL;
9237                 bool ok;
9238
9239                 ulocks = talloc_array(
9240                         req, struct smbd_lock_element, num_ulocks);
9241                 if (ulocks == NULL) {
9242                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9243                         END_PROFILE(SMBlockingX);
9244                         return;
9245                 }
9246
9247                 /*
9248                  * Data now points at the beginning of the list of
9249                  * smb_unlkrng structs
9250                  */
9251                 for (i = 0; i < num_ulocks; i++) {
9252                         ulocks[i].req_guid = smbd_request_guid(req,
9253                                 UINT16_MAX - i),
9254                         ulocks[i].smblctx = get_lock_pid(
9255                                 data, i, large_file_format);
9256                         ulocks[i].count = get_lock_count(
9257                                 data, i, large_file_format);
9258                         ulocks[i].offset = get_lock_offset(
9259                                 data, i, large_file_format);
9260                         ulocks[i].brltype = UNLOCK_LOCK;
9261                 }
9262
9263                 /*
9264                  * Unlock cancels pending locks
9265                  */
9266
9267                 ok = smbd_smb1_brl_finish_by_lock(
9268                         fsp,
9269                         large_file_format,
9270                         WINDOWS_LOCK,
9271                         ulocks[0],
9272                         NT_STATUS_OK);
9273                 if (ok) {
9274                         reply_outbuf(req, 2, 0);
9275                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9276                         SSVAL(req->outbuf, smb_vwv1, 0);
9277                         END_PROFILE(SMBlockingX);
9278                         return;
9279                 }
9280
9281                 status = smbd_do_unlocking(
9282                         req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9283                 TALLOC_FREE(ulocks);
9284                 if (!NT_STATUS_IS_OK(status)) {
9285                         END_PROFILE(SMBlockingX);
9286                         reply_nterror(req, status);
9287                         return;
9288                 }
9289         }
9290
9291         /* Now do any requested locks */
9292         data += ((large_file_format ? 20 : 10)*num_ulocks);
9293
9294         /* Data now points at the beginning of the list
9295            of smb_lkrng structs */
9296
9297         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9298                 brltype = READ_LOCK;
9299         } else {
9300                 brltype = WRITE_LOCK;
9301         }
9302
9303         locks = talloc_array(req, struct smbd_lock_element, num_locks);
9304         if (locks == NULL) {
9305                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9306                 END_PROFILE(SMBlockingX);
9307                 return;
9308         }
9309
9310         for (i = 0; i < num_locks; i++) {
9311                 locks[i].req_guid = smbd_request_guid(req, i),
9312                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9313                 locks[i].count = get_lock_count(data, i, large_file_format);
9314                 locks[i].offset = get_lock_offset(data, i, large_file_format);
9315                 locks[i].brltype = brltype;
9316         }
9317
9318         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9319
9320                 bool ok;
9321
9322                 if (num_locks == 0) {
9323                         /* See smbtorture3 lock11 test */
9324                         reply_outbuf(req, 2, 0);
9325                         /* andx chain ends */
9326                         SSVAL(req->outbuf, smb_vwv0, 0xff);
9327                         SSVAL(req->outbuf, smb_vwv1, 0);
9328                         END_PROFILE(SMBlockingX);
9329                         return;
9330                 }
9331
9332                 ok = smbd_smb1_brl_finish_by_lock(
9333                         fsp,
9334                         large_file_format,
9335                         WINDOWS_LOCK,
9336                         locks[0], /* Windows only cancels the first lock */
9337                         NT_STATUS_FILE_LOCK_CONFLICT);
9338
9339                 if (!ok) {
9340                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9341                         END_PROFILE(SMBlockingX);
9342                         return;
9343                 }
9344
9345                 reply_outbuf(req, 2, 0);
9346                 SSVAL(req->outbuf, smb_vwv0, 0xff);
9347                 SSVAL(req->outbuf, smb_vwv1, 0);
9348                 END_PROFILE(SMBlockingX);
9349                 return;
9350         }
9351
9352         subreq = smbd_smb1_do_locks_send(
9353                 fsp,
9354                 req->sconn->ev_ctx,
9355                 &req,
9356                 fsp,
9357                 lock_timeout,
9358                 large_file_format,
9359                 WINDOWS_LOCK,
9360                 num_locks,
9361                 locks);
9362         if (subreq == NULL) {
9363                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9364                 END_PROFILE(SMBlockingX);
9365                 return;
9366         }
9367         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9368         END_PROFILE(SMBlockingX);
9369 }
9370
9371 static void reply_lockingx_done(struct tevent_req *subreq)
9372 {
9373         struct smb_request *req = NULL;
9374         NTSTATUS status;
9375         bool ok;
9376
9377         START_PROFILE(SMBlockingX);
9378
9379         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9380         SMB_ASSERT(ok);
9381
9382         status = smbd_smb1_do_locks_recv(subreq);
9383         TALLOC_FREE(subreq);
9384
9385         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9386
9387         if (NT_STATUS_IS_OK(status)) {
9388                 reply_outbuf(req, 2, 0);
9389                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9390                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
9391         } else {
9392                 reply_nterror(req, status);
9393         }
9394
9395         ok = srv_send_smb(req->xconn,
9396                           (char *)req->outbuf,
9397                           true,
9398                           req->seqnum+1,
9399                           IS_CONN_ENCRYPTED(req->conn),
9400                           NULL);
9401         if (!ok) {
9402                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9403         }
9404         TALLOC_FREE(req);
9405         END_PROFILE(SMBlockingX);
9406 }
9407
9408 #undef DBGC_CLASS
9409 #define DBGC_CLASS DBGC_ALL
9410
9411 /****************************************************************************
9412  Reply to a SMBreadbmpx (read block multiplex) request.
9413  Always reply with an error, if someone has a platform really needs this,
9414  please contact vl@samba.org
9415 ****************************************************************************/
9416
9417 void reply_readbmpx(struct smb_request *req)
9418 {
9419         START_PROFILE(SMBreadBmpx);
9420         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9421         END_PROFILE(SMBreadBmpx);
9422         return;
9423 }
9424
9425 /****************************************************************************
9426  Reply to a SMBreadbs (read block multiplex secondary) request.
9427  Always reply with an error, if someone has a platform really needs this,
9428  please contact vl@samba.org
9429 ****************************************************************************/
9430
9431 void reply_readbs(struct smb_request *req)
9432 {
9433         START_PROFILE(SMBreadBs);
9434         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9435         END_PROFILE(SMBreadBs);
9436         return;
9437 }
9438
9439 /****************************************************************************
9440  Reply to a SMBsetattrE.
9441 ****************************************************************************/
9442
9443 void reply_setattrE(struct smb_request *req)
9444 {
9445         connection_struct *conn = req->conn;
9446         struct smb_file_time ft;
9447         files_struct *fsp;
9448         NTSTATUS status;
9449
9450         START_PROFILE(SMBsetattrE);
9451         init_smb_file_time(&ft);
9452
9453         if (req->wct < 7) {
9454                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9455                 goto out;
9456         }
9457
9458         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9459
9460         if(!fsp || (fsp->conn != conn)) {
9461                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9462                 goto out;
9463         }
9464
9465         /*
9466          * Convert the DOS times into unix times.
9467          */
9468
9469         ft.atime = time_t_to_full_timespec(
9470             srv_make_unix_date2(req->vwv+3));
9471         ft.mtime = time_t_to_full_timespec(
9472             srv_make_unix_date2(req->vwv+5));
9473         ft.create_time = time_t_to_full_timespec(
9474             srv_make_unix_date2(req->vwv+1));
9475
9476         reply_outbuf(req, 0, 0);
9477
9478         /* 
9479          * Patch from Ray Frush <frush@engr.colostate.edu>
9480          * Sometimes times are sent as zero - ignore them.
9481          */
9482
9483         /* Ensure we have a valid stat struct for the source. */
9484         status = vfs_stat_fsp(fsp);
9485         if (!NT_STATUS_IS_OK(status)) {
9486                 reply_nterror(req, status);
9487                 goto out;
9488         }
9489
9490         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9491                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9492                 goto out;
9493         }
9494
9495         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9496         if (!NT_STATUS_IS_OK(status)) {
9497                 reply_nterror(req, status);
9498                 goto out;
9499         }
9500
9501         if (fsp->fsp_flags.modified) {
9502                 trigger_write_time_update_immediate(fsp);
9503         }
9504
9505         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9506                " createtime=%u\n",
9507                 fsp_fnum_dbg(fsp),
9508                 (unsigned int)ft.atime.tv_sec,
9509                 (unsigned int)ft.mtime.tv_sec,
9510                 (unsigned int)ft.create_time.tv_sec
9511                 ));
9512  out:
9513         END_PROFILE(SMBsetattrE);
9514         return;
9515 }
9516
9517
9518 /* Back from the dead for OS/2..... JRA. */
9519
9520 /****************************************************************************
9521  Reply to a SMBwritebmpx (write block multiplex primary) request.
9522  Always reply with an error, if someone has a platform really needs this,
9523  please contact vl@samba.org
9524 ****************************************************************************/
9525
9526 void reply_writebmpx(struct smb_request *req)
9527 {
9528         START_PROFILE(SMBwriteBmpx);
9529         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9530         END_PROFILE(SMBwriteBmpx);
9531         return;
9532 }
9533
9534 /****************************************************************************
9535  Reply to a SMBwritebs (write block multiplex secondary) request.
9536  Always reply with an error, if someone has a platform really needs this,
9537  please contact vl@samba.org
9538 ****************************************************************************/
9539
9540 void reply_writebs(struct smb_request *req)
9541 {
9542         START_PROFILE(SMBwriteBs);
9543         reply_force_doserror(req, ERRSRV, ERRuseSTD);
9544         END_PROFILE(SMBwriteBs);
9545         return;
9546 }
9547
9548 /****************************************************************************
9549  Reply to a SMBgetattrE.
9550 ****************************************************************************/
9551
9552 void reply_getattrE(struct smb_request *req)
9553 {
9554         connection_struct *conn = req->conn;
9555         int mode;
9556         files_struct *fsp;
9557         struct timespec create_ts;
9558         NTSTATUS status;
9559
9560         START_PROFILE(SMBgetattrE);
9561
9562         if (req->wct < 1) {
9563                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9564                 END_PROFILE(SMBgetattrE);
9565                 return;
9566         }
9567
9568         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9569
9570         if(!fsp || (fsp->conn != conn)) {
9571                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9572                 END_PROFILE(SMBgetattrE);
9573                 return;
9574         }
9575
9576         /* Do an fstat on this file */
9577         status = vfs_stat_fsp(fsp);
9578         if (!NT_STATUS_IS_OK(status)) {
9579                 reply_nterror(req, status);
9580                 END_PROFILE(SMBgetattrE);
9581                 return;
9582         }
9583
9584         mode = dos_mode(conn, fsp->fsp_name);
9585
9586         /*
9587          * Convert the times into dos times. Set create
9588          * date to be last modify date as UNIX doesn't save
9589          * this.
9590          */
9591
9592         reply_outbuf(req, 11, 0);
9593
9594         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9595         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9596         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9597                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9598         /* Should we check pending modtime here ? JRA */
9599         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9600                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9601
9602         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9603                 SIVAL(req->outbuf, smb_vwv6, 0);
9604                 SIVAL(req->outbuf, smb_vwv8, 0);
9605         } else {
9606                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9607                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9608                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9609         }
9610         SSVAL(req->outbuf,smb_vwv10, mode);
9611
9612         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9613
9614         END_PROFILE(SMBgetattrE);
9615         return;
9616 }