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