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