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