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