s3: smbd: SMB1 add range checks to reply_search().
[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         if (smbreq_bufrem(req, p) < 3) {
1805                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1806                 goto out;
1807         }
1808
1809         p++;
1810         status_len = SVAL(p, 0);
1811         p += 2;
1812
1813         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1814
1815         if (status_len == 0) {
1816                 struct smb_filename *smb_dname = NULL;
1817                 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1818                         ucf_flags_from_smb_request(req);
1819                 nt_status = filename_convert(ctx, conn,
1820                                              path,
1821                                              ucf_flags,
1822                                              NULL,
1823                                              &mask_contains_wcard,
1824                                              &smb_fname);
1825                 if (!NT_STATUS_IS_OK(nt_status)) {
1826                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1827                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1828                                                 ERRSRV, ERRbadpath);
1829                                 goto out;
1830                         }
1831                         reply_nterror(req, nt_status);
1832                         goto out;
1833                 }
1834
1835                 directory = smb_fname->base_name;
1836
1837                 p = strrchr_m(directory,'/');
1838                 if ((p != NULL) && (*directory != '/')) {
1839                         mask = talloc_strdup(ctx, p + 1);
1840                         directory = talloc_strndup(ctx, directory,
1841                                                    PTR_DIFF(p, directory));
1842                 } else {
1843                         mask = talloc_strdup(ctx, directory);
1844                         directory = talloc_strdup(ctx,".");
1845                 }
1846
1847                 if (!directory) {
1848                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1849                         goto out;
1850                 }
1851
1852                 memset((char *)status,'\0',21);
1853                 SCVAL(status,0,(dirtype & 0x1F));
1854
1855                 smb_dname = synthetic_smb_fname(talloc_tos(),
1856                                         directory,
1857                                         NULL,
1858                                         NULL,
1859                                         smb_fname->flags);
1860                 if (smb_dname == NULL) {
1861                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1862                         goto out;
1863                 }
1864
1865                 nt_status = dptr_create(conn,
1866                                         NULL, /* req */
1867                                         NULL, /* fsp */
1868                                         smb_dname,
1869                                         True,
1870                                         expect_close,
1871                                         req->smbpid,
1872                                         mask,
1873                                         mask_contains_wcard,
1874                                         dirtype,
1875                                         &dirptr);
1876
1877                 TALLOC_FREE(smb_dname);
1878
1879                 if (!NT_STATUS_IS_OK(nt_status)) {
1880                         reply_nterror(req, nt_status);
1881                         goto out;
1882                 }
1883                 dptr_num = dptr_dnum(dirptr);
1884         } else {
1885                 int status_dirtype;
1886                 const char *dirpath;
1887
1888                 if (smbreq_bufrem(req, p) < 21) {
1889                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1890                         goto out;
1891                 }
1892
1893                 memcpy(status,p,21);
1894                 status_dirtype = CVAL(status,0) & 0x1F;
1895                 if (status_dirtype != (dirtype & 0x1F)) {
1896                         dirtype = status_dirtype;
1897                 }
1898
1899                 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1900                 if (!dirptr) {
1901                         goto SearchEmpty;
1902                 }
1903                 dirpath = dptr_path(sconn, dptr_num);
1904                 directory = talloc_strdup(ctx, dirpath);
1905                 if (!directory) {
1906                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1907                         goto out;
1908                 }
1909
1910                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1911                 if (!mask) {
1912                         goto SearchEmpty;
1913                 }
1914                 /*
1915                  * For a 'continue' search we have no string. So
1916                  * check from the initial saved string.
1917                  */
1918                 if (!req->posix_pathnames) {
1919                         mask_contains_wcard = ms_has_wild(mask);
1920                 }
1921                 dirtype = dptr_attr(sconn, dptr_num);
1922         }
1923
1924         DEBUG(4,("dptr_num is %d\n",dptr_num));
1925
1926         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1927                 char buf[DIR_STRUCT_SIZE];
1928                 memcpy(buf,status,21);
1929                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1930                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1931                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1932                         goto out;
1933                 }
1934                 dptr_fill(sconn, buf+12,dptr_num);
1935                 if (dptr_zero(buf+12) && (status_len==0)) {
1936                         numentries = 1;
1937                 } else {
1938                         numentries = 0;
1939                 }
1940                 if (message_push_blob(&req->outbuf,
1941                                       data_blob_const(buf, sizeof(buf)))
1942                     == -1) {
1943                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1944                         goto out;
1945                 }
1946         } else {
1947                 unsigned int i;
1948                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1949                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1950
1951                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1952
1953                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1954                          directory,lp_dont_descend(ctx, SNUM(conn))));
1955                 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1956                         check_descend = True;
1957                 }
1958
1959                 for (i=numentries;(i<maxentries) && !finished;i++) {
1960                         finished = !get_dir_entry(ctx,
1961                                                   dirptr,
1962                                                   mask,
1963                                                   dirtype,
1964                                                   &fname,
1965                                                   &size,
1966                                                   &mode,
1967                                                   &date,
1968                                                   check_descend,
1969                                                   ask_sharemode);
1970                         if (!finished) {
1971                                 char buf[DIR_STRUCT_SIZE];
1972                                 memcpy(buf,status,21);
1973                                 if (!make_dir_struct(ctx,
1974                                                 buf,
1975                                                 mask,
1976                                                 fname,
1977                                                 size,
1978                                                 mode,
1979                                                 convert_timespec_to_time_t(date),
1980                                                 !allow_long_path_components)) {
1981                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1982                                         goto out;
1983                                 }
1984                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1985                                         break;
1986                                 }
1987                                 if (message_push_blob(&req->outbuf,
1988                                                       data_blob_const(buf, sizeof(buf)))
1989                                     == -1) {
1990                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1991                                         goto out;
1992                                 }
1993                                 numentries++;
1994                         }
1995                 }
1996         }
1997
1998   SearchEmpty:
1999
2000         /* If we were called as SMBffirst with smb_search_id == NULL
2001                 and no entries were found then return error and close dirptr 
2002                 (X/Open spec) */
2003
2004         if (numentries == 0) {
2005                 dptr_close(sconn, &dptr_num);
2006         } else if(expect_close && status_len == 0) {
2007                 /* Close the dptr - we know it's gone */
2008                 dptr_close(sconn, &dptr_num);
2009         }
2010
2011         /* If we were called as SMBfunique, then we can close the dirptr now ! */
2012         if(dptr_num >= 0 && req->cmd == SMBfunique) {
2013                 dptr_close(sconn, &dptr_num);
2014         }
2015
2016         if ((numentries == 0) && !mask_contains_wcard) {
2017                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2018                 goto out;
2019         }
2020
2021         SSVAL(req->outbuf,smb_vwv0,numentries);
2022         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2023         SCVAL(smb_buf(req->outbuf),0,5);
2024         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2025
2026         /* The replies here are never long name. */
2027         SSVAL(req->outbuf, smb_flg2,
2028               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2029         if (!allow_long_path_components) {
2030                 SSVAL(req->outbuf, smb_flg2,
2031                       SVAL(req->outbuf, smb_flg2)
2032                       & (~FLAGS2_LONG_PATH_COMPONENTS));
2033         }
2034
2035         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2036         SSVAL(req->outbuf, smb_flg2,
2037               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2038
2039         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2040                 smb_fn_name(req->cmd),
2041                 mask,
2042                 directory,
2043                 dirtype,
2044                 numentries,
2045                 maxentries ));
2046  out:
2047         TALLOC_FREE(directory);
2048         TALLOC_FREE(mask);
2049         TALLOC_FREE(smb_fname);
2050         END_PROFILE(SMBsearch);
2051         return;
2052 }
2053
2054 /****************************************************************************
2055  Reply to a fclose (stop directory search).
2056 ****************************************************************************/
2057
2058 void reply_fclose(struct smb_request *req)
2059 {
2060         int status_len;
2061         char status[21];
2062         int dptr_num= -2;
2063         const char *p;
2064         char *path = NULL;
2065         NTSTATUS err;
2066         bool path_contains_wcard = False;
2067         TALLOC_CTX *ctx = talloc_tos();
2068         struct smbd_server_connection *sconn = req->sconn;
2069
2070         START_PROFILE(SMBfclose);
2071
2072         if (req->posix_pathnames) {
2073                 reply_unknown_new(req, req->cmd);
2074                 END_PROFILE(SMBfclose);
2075                 return;
2076         }
2077
2078         p = (const char *)req->buf + 1;
2079         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2080                                        &err, &path_contains_wcard);
2081         if (!NT_STATUS_IS_OK(err)) {
2082                 reply_nterror(req, err);
2083                 END_PROFILE(SMBfclose);
2084                 return;
2085         }
2086         p++;
2087         status_len = SVAL(p,0);
2088         p += 2;
2089
2090         if (status_len == 0) {
2091                 reply_force_doserror(req, ERRSRV, ERRsrverror);
2092                 END_PROFILE(SMBfclose);
2093                 return;
2094         }
2095
2096         memcpy(status,p,21);
2097
2098         if(dptr_fetch(sconn, status+12,&dptr_num)) {
2099                 /*  Close the dptr - we know it's gone */
2100                 dptr_close(sconn, &dptr_num);
2101         }
2102
2103         reply_outbuf(req, 1, 0);
2104         SSVAL(req->outbuf,smb_vwv0,0);
2105
2106         DEBUG(3,("search close\n"));
2107
2108         END_PROFILE(SMBfclose);
2109         return;
2110 }
2111
2112 /****************************************************************************
2113  Reply to an open.
2114 ****************************************************************************/
2115
2116 void reply_open(struct smb_request *req)
2117 {
2118         connection_struct *conn = req->conn;
2119         struct smb_filename *smb_fname = NULL;
2120         char *fname = NULL;
2121         uint32_t fattr=0;
2122         off_t size = 0;
2123         time_t mtime=0;
2124         int info;
2125         files_struct *fsp;
2126         int oplock_request;
2127         int deny_mode;
2128         uint32_t dos_attr;
2129         uint32_t access_mask;
2130         uint32_t share_mode;
2131         uint32_t create_disposition;
2132         uint32_t create_options = 0;
2133         uint32_t private_flags = 0;
2134         NTSTATUS status;
2135         uint32_t ucf_flags;
2136         TALLOC_CTX *ctx = talloc_tos();
2137
2138         START_PROFILE(SMBopen);
2139
2140         if (req->wct < 2) {
2141                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2142                 goto out;
2143         }
2144
2145         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2146         deny_mode = SVAL(req->vwv+0, 0);
2147         dos_attr = SVAL(req->vwv+1, 0);
2148
2149         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2150                             STR_TERMINATE, &status);
2151         if (!NT_STATUS_IS_OK(status)) {
2152                 reply_nterror(req, status);
2153                 goto out;
2154         }
2155
2156         if (!map_open_params_to_ntcreate(fname, deny_mode,
2157                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
2158                                          &share_mode, &create_disposition,
2159                                          &create_options, &private_flags)) {
2160                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2161                 goto out;
2162         }
2163
2164         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2165
2166         status = filename_convert(ctx,
2167                                 conn,
2168                                 fname,
2169                                 ucf_flags,
2170                                 NULL,
2171                                 NULL,
2172                                 &smb_fname);
2173         if (!NT_STATUS_IS_OK(status)) {
2174                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2175                         reply_botherror(req,
2176                                         NT_STATUS_PATH_NOT_COVERED,
2177                                         ERRSRV, ERRbadpath);
2178                         goto out;
2179                 }
2180                 reply_nterror(req, status);
2181                 goto out;
2182         }
2183
2184         status = SMB_VFS_CREATE_FILE(
2185                 conn,                                   /* conn */
2186                 req,                                    /* req */
2187                 0,                                      /* root_dir_fid */
2188                 smb_fname,                              /* fname */
2189                 access_mask,                            /* access_mask */
2190                 share_mode,                             /* share_access */
2191                 create_disposition,                     /* create_disposition*/
2192                 create_options,                         /* create_options */
2193                 dos_attr,                               /* file_attributes */
2194                 oplock_request,                         /* oplock_request */
2195                 NULL,                                   /* lease */
2196                 0,                                      /* allocation_size */
2197                 private_flags,
2198                 NULL,                                   /* sd */
2199                 NULL,                                   /* ea_list */
2200                 &fsp,                                   /* result */
2201                 &info,                                  /* pinfo */
2202                 NULL, NULL);                            /* create context */
2203
2204         if (!NT_STATUS_IS_OK(status)) {
2205                 if (open_was_deferred(req->xconn, req->mid)) {
2206                         /* We have re-scheduled this call. */
2207                         goto out;
2208                 }
2209                 reply_openerror(req, status);
2210                 goto out;
2211         }
2212
2213         /* Ensure we're pointing at the correct stat struct. */
2214         TALLOC_FREE(smb_fname);
2215         smb_fname = fsp->fsp_name;
2216
2217         size = smb_fname->st.st_ex_size;
2218         fattr = dos_mode(conn, smb_fname);
2219
2220         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2221
2222         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2223                 DEBUG(3,("attempt to open a directory %s\n",
2224                          fsp_str_dbg(fsp)));
2225                 close_file(req, fsp, ERROR_CLOSE);
2226                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2227                         ERRDOS, ERRnoaccess);
2228                 goto out;
2229         }
2230
2231         reply_outbuf(req, 7, 0);
2232         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2233         SSVAL(req->outbuf,smb_vwv1,fattr);
2234         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2235                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2236         } else {
2237                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2238         }
2239         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2240         SSVAL(req->outbuf,smb_vwv6,deny_mode);
2241
2242         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2243                 SCVAL(req->outbuf,smb_flg,
2244                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2245         }
2246
2247         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2248                 SCVAL(req->outbuf,smb_flg,
2249                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2250         }
2251  out:
2252         END_PROFILE(SMBopen);
2253         return;
2254 }
2255
2256 /****************************************************************************
2257  Reply to an open and X.
2258 ****************************************************************************/
2259
2260 void reply_open_and_X(struct smb_request *req)
2261 {
2262         connection_struct *conn = req->conn;
2263         struct smb_filename *smb_fname = NULL;
2264         char *fname = NULL;
2265         uint16_t open_flags;
2266         int deny_mode;
2267         uint32_t smb_attr;
2268         /* Breakout the oplock request bits so we can set the
2269                 reply bits separately. */
2270         int ex_oplock_request;
2271         int core_oplock_request;
2272         int oplock_request;
2273 #if 0
2274         int smb_sattr = SVAL(req->vwv+4, 0);
2275         uint32_t smb_time = make_unix_date3(req->vwv+6);
2276 #endif
2277         int smb_ofun;
2278         uint32_t fattr=0;
2279         int mtime=0;
2280         int smb_action = 0;
2281         files_struct *fsp;
2282         NTSTATUS status;
2283         uint64_t allocation_size;
2284         ssize_t retval = -1;
2285         uint32_t access_mask;
2286         uint32_t share_mode;
2287         uint32_t create_disposition;
2288         uint32_t create_options = 0;
2289         uint32_t private_flags = 0;
2290         uint32_t ucf_flags;
2291         TALLOC_CTX *ctx = talloc_tos();
2292
2293         START_PROFILE(SMBopenX);
2294
2295         if (req->wct < 15) {
2296                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2297                 goto out;
2298         }
2299
2300         open_flags = SVAL(req->vwv+2, 0);
2301         deny_mode = SVAL(req->vwv+3, 0);
2302         smb_attr = SVAL(req->vwv+5, 0);
2303         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2304         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2305         oplock_request = ex_oplock_request | core_oplock_request;
2306         smb_ofun = SVAL(req->vwv+8, 0);
2307         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2308
2309         /* If it's an IPC, pass off the pipe handler. */
2310         if (IS_IPC(conn)) {
2311                 if (lp_nt_pipe_support()) {
2312                         reply_open_pipe_and_X(conn, req);
2313                 } else {
2314                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2315                 }
2316                 goto out;
2317         }
2318
2319         /* XXXX we need to handle passed times, sattr and flags */
2320         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2321                         STR_TERMINATE, &status);
2322         if (!NT_STATUS_IS_OK(status)) {
2323                 reply_nterror(req, status);
2324                 goto out;
2325         }
2326
2327         if (!map_open_params_to_ntcreate(fname, deny_mode,
2328                                          smb_ofun,
2329                                          &access_mask, &share_mode,
2330                                          &create_disposition,
2331                                          &create_options,
2332                                          &private_flags)) {
2333                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2334                 goto out;
2335         }
2336
2337         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2338
2339         status = filename_convert(ctx,
2340                                 conn,
2341                                 fname,
2342                                 ucf_flags,
2343                                 NULL,
2344                                 NULL,
2345                                 &smb_fname);
2346         if (!NT_STATUS_IS_OK(status)) {
2347                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2348                         reply_botherror(req,
2349                                         NT_STATUS_PATH_NOT_COVERED,
2350                                         ERRSRV, ERRbadpath);
2351                         goto out;
2352                 }
2353                 reply_nterror(req, status);
2354                 goto out;
2355         }
2356
2357         status = SMB_VFS_CREATE_FILE(
2358                 conn,                                   /* conn */
2359                 req,                                    /* req */
2360                 0,                                      /* root_dir_fid */
2361                 smb_fname,                              /* fname */
2362                 access_mask,                            /* access_mask */
2363                 share_mode,                             /* share_access */
2364                 create_disposition,                     /* create_disposition*/
2365                 create_options,                         /* create_options */
2366                 smb_attr,                               /* file_attributes */
2367                 oplock_request,                         /* oplock_request */
2368                 NULL,                                   /* lease */
2369                 0,                                      /* allocation_size */
2370                 private_flags,
2371                 NULL,                                   /* sd */
2372                 NULL,                                   /* ea_list */
2373                 &fsp,                                   /* result */
2374                 &smb_action,                            /* pinfo */
2375                 NULL, NULL);                            /* create context */
2376
2377         if (!NT_STATUS_IS_OK(status)) {
2378                 if (open_was_deferred(req->xconn, req->mid)) {
2379                         /* We have re-scheduled this call. */
2380                         goto out;
2381                 }
2382                 reply_openerror(req, status);
2383                 goto out;
2384         }
2385
2386         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2387            if the file is truncated or created. */
2388         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2389                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2390                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2391                         close_file(req, fsp, ERROR_CLOSE);
2392                         reply_nterror(req, NT_STATUS_DISK_FULL);
2393                         goto out;
2394                 }
2395                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2396                 if (retval < 0) {
2397                         close_file(req, fsp, ERROR_CLOSE);
2398                         reply_nterror(req, NT_STATUS_DISK_FULL);
2399                         goto out;
2400                 }
2401                 status = vfs_stat_fsp(fsp);
2402                 if (!NT_STATUS_IS_OK(status)) {
2403                         close_file(req, fsp, ERROR_CLOSE);
2404                         reply_nterror(req, status);
2405                         goto out;
2406                 }
2407         }
2408
2409         fattr = dos_mode(conn, fsp->fsp_name);
2410         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2411         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2412                 close_file(req, fsp, ERROR_CLOSE);
2413                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2414                 goto out;
2415         }
2416
2417         /* If the caller set the extended oplock request bit
2418                 and we granted one (by whatever means) - set the
2419                 correct bit for extended oplock reply.
2420         */
2421
2422         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2423                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2424         }
2425
2426         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2427                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2428         }
2429
2430         /* If the caller set the core oplock request bit
2431                 and we granted one (by whatever means) - set the
2432                 correct bit for core oplock reply.
2433         */
2434
2435         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2436                 reply_outbuf(req, 19, 0);
2437         } else {
2438                 reply_outbuf(req, 15, 0);
2439         }
2440
2441         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2442         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2443
2444         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2445                 SCVAL(req->outbuf, smb_flg,
2446                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2447         }
2448
2449         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2450                 SCVAL(req->outbuf, smb_flg,
2451                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2452         }
2453
2454         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2455         SSVAL(req->outbuf,smb_vwv3,fattr);
2456         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2457                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2458         } else {
2459                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2460         }
2461         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2462         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2463         SSVAL(req->outbuf,smb_vwv11,smb_action);
2464
2465         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2466                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2467         }
2468
2469  out:
2470         TALLOC_FREE(smb_fname);
2471         END_PROFILE(SMBopenX);
2472         return;
2473 }
2474
2475 /****************************************************************************
2476  Reply to a SMBulogoffX.
2477 ****************************************************************************/
2478
2479 void reply_ulogoffX(struct smb_request *req)
2480 {
2481         struct smbd_server_connection *sconn = req->sconn;
2482         struct user_struct *vuser;
2483         struct smbXsrv_session *session = NULL;
2484         NTSTATUS status;
2485
2486         START_PROFILE(SMBulogoffX);
2487
2488         vuser = get_valid_user_struct(sconn, req->vuid);
2489
2490         if(vuser == NULL) {
2491                 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2492                          (unsigned long long)req->vuid));
2493
2494                 req->vuid = UID_FIELD_INVALID;
2495                 reply_force_doserror(req, ERRSRV, ERRbaduid);
2496                 END_PROFILE(SMBulogoffX);
2497                 return;
2498         }
2499
2500         session = vuser->session;
2501         vuser = NULL;
2502
2503         /*
2504          * TODO: cancel all outstanding requests on the session
2505          */
2506         status = smbXsrv_session_logoff(session);
2507         if (!NT_STATUS_IS_OK(status)) {
2508                 DEBUG(0, ("reply_ulogoff: "
2509                           "smbXsrv_session_logoff() failed: %s\n",
2510                           nt_errstr(status)));
2511                 /*
2512                  * If we hit this case, there is something completely
2513                  * wrong, so we better disconnect the transport connection.
2514                  */
2515                 END_PROFILE(SMBulogoffX);
2516                 exit_server(__location__ ": smbXsrv_session_logoff failed");
2517                 return;
2518         }
2519
2520         TALLOC_FREE(session);
2521
2522         reply_outbuf(req, 2, 0);
2523         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2524         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2525
2526         DEBUG(3, ("ulogoffX vuid=%llu\n",
2527                   (unsigned long long)req->vuid));
2528
2529         END_PROFILE(SMBulogoffX);
2530         req->vuid = UID_FIELD_INVALID;
2531 }
2532
2533 /****************************************************************************
2534  Reply to a mknew or a create.
2535 ****************************************************************************/
2536
2537 void reply_mknew(struct smb_request *req)
2538 {
2539         connection_struct *conn = req->conn;
2540         struct smb_filename *smb_fname = NULL;
2541         char *fname = NULL;
2542         uint32_t fattr = 0;
2543         struct smb_file_time ft;
2544         files_struct *fsp;
2545         int oplock_request = 0;
2546         NTSTATUS status;
2547         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2548         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2549         uint32_t create_disposition;
2550         uint32_t create_options = 0;
2551         uint32_t ucf_flags;
2552         TALLOC_CTX *ctx = talloc_tos();
2553
2554         START_PROFILE(SMBcreate);
2555         ZERO_STRUCT(ft);
2556
2557         if (req->wct < 3) {
2558                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2559                 goto out;
2560         }
2561
2562         fattr = SVAL(req->vwv+0, 0);
2563         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2564
2565         if (req->cmd == SMBmknew) {
2566                 /* We should fail if file exists. */
2567                 create_disposition = FILE_CREATE;
2568         } else {
2569                 /* Create if file doesn't exist, truncate if it does. */
2570                 create_disposition = FILE_OVERWRITE_IF;
2571         }
2572
2573         /* mtime. */
2574         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2575
2576         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2577                             STR_TERMINATE, &status);
2578         if (!NT_STATUS_IS_OK(status)) {
2579                 reply_nterror(req, status);
2580                 goto out;
2581         }
2582
2583         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2584         status = filename_convert(ctx,
2585                                 conn,
2586                                 fname,
2587                                 ucf_flags,
2588                                 NULL,
2589                                 NULL,
2590                                 &smb_fname);
2591         if (!NT_STATUS_IS_OK(status)) {
2592                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2593                         reply_botherror(req,
2594                                         NT_STATUS_PATH_NOT_COVERED,
2595                                         ERRSRV, ERRbadpath);
2596                         goto out;
2597                 }
2598                 reply_nterror(req, status);
2599                 goto out;
2600         }
2601
2602         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2603                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2604                          "please report this\n",
2605                          smb_fname_str_dbg(smb_fname)));
2606         }
2607
2608         status = SMB_VFS_CREATE_FILE(
2609                 conn,                                   /* conn */
2610                 req,                                    /* req */
2611                 0,                                      /* root_dir_fid */
2612                 smb_fname,                              /* fname */
2613                 access_mask,                            /* access_mask */
2614                 share_mode,                             /* share_access */
2615                 create_disposition,                     /* create_disposition*/
2616                 create_options,                         /* create_options */
2617                 fattr,                                  /* file_attributes */
2618                 oplock_request,                         /* oplock_request */
2619                 NULL,                                   /* lease */
2620                 0,                                      /* allocation_size */
2621                 0,                                      /* private_flags */
2622                 NULL,                                   /* sd */
2623                 NULL,                                   /* ea_list */
2624                 &fsp,                                   /* result */
2625                 NULL,                                   /* pinfo */
2626                 NULL, NULL);                            /* create context */
2627
2628         if (!NT_STATUS_IS_OK(status)) {
2629                 if (open_was_deferred(req->xconn, req->mid)) {
2630                         /* We have re-scheduled this call. */
2631                         goto out;
2632                 }
2633                 reply_openerror(req, status);
2634                 goto out;
2635         }
2636
2637         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2638         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2639         if (!NT_STATUS_IS_OK(status)) {
2640                 END_PROFILE(SMBcreate);
2641                 goto out;
2642         }
2643
2644         reply_outbuf(req, 1, 0);
2645         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2646
2647         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2648                 SCVAL(req->outbuf,smb_flg,
2649                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2650         }
2651
2652         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2653                 SCVAL(req->outbuf,smb_flg,
2654                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2655         }
2656
2657         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2658         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2659                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2660                   (unsigned int)fattr));
2661
2662  out:
2663         TALLOC_FREE(smb_fname);
2664         END_PROFILE(SMBcreate);
2665         return;
2666 }
2667
2668 /****************************************************************************
2669  Reply to a create temporary file.
2670 ****************************************************************************/
2671
2672 void reply_ctemp(struct smb_request *req)
2673 {
2674         connection_struct *conn = req->conn;
2675         struct smb_filename *smb_fname = NULL;
2676         char *wire_name = NULL;
2677         char *fname = NULL;
2678         uint32_t fattr;
2679         files_struct *fsp;
2680         int oplock_request;
2681         char *s;
2682         NTSTATUS status;
2683         int i;
2684         uint32_t ucf_flags;
2685         TALLOC_CTX *ctx = talloc_tos();
2686
2687         START_PROFILE(SMBctemp);
2688
2689         if (req->wct < 3) {
2690                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2691                 goto out;
2692         }
2693
2694         fattr = SVAL(req->vwv+0, 0);
2695         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2696
2697         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2698                             STR_TERMINATE, &status);
2699         if (!NT_STATUS_IS_OK(status)) {
2700                 reply_nterror(req, status);
2701                 goto out;
2702         }
2703
2704         for (i = 0; i < 10; i++) {
2705                 if (*wire_name) {
2706                         fname = talloc_asprintf(ctx,
2707                                         "%s/TMP%s",
2708                                         wire_name,
2709                                         generate_random_str_list(ctx, 5, "0123456789"));
2710                 } else {
2711                         fname = talloc_asprintf(ctx,
2712                                         "TMP%s",
2713                                         generate_random_str_list(ctx, 5, "0123456789"));
2714                 }
2715
2716                 if (!fname) {
2717                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2718                         goto out;
2719                 }
2720
2721                 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2722                 status = filename_convert(ctx, conn,
2723                                 fname,
2724                                 ucf_flags,
2725                                 NULL,
2726                                 NULL,
2727                                 &smb_fname);
2728                 if (!NT_STATUS_IS_OK(status)) {
2729                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2730                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2731                                         ERRSRV, ERRbadpath);
2732                                 goto out;
2733                         }
2734                         reply_nterror(req, status);
2735                         goto out;
2736                 }
2737
2738                 /* Create the file. */
2739                 status = SMB_VFS_CREATE_FILE(
2740                         conn,                                   /* conn */
2741                         req,                                    /* req */
2742                         0,                                      /* root_dir_fid */
2743                         smb_fname,                              /* fname */
2744                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2745                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2746                         FILE_CREATE,                            /* create_disposition*/
2747                         0,                                      /* create_options */
2748                         fattr,                                  /* file_attributes */
2749                         oplock_request,                         /* oplock_request */
2750                         NULL,                                   /* lease */
2751                         0,                                      /* allocation_size */
2752                         0,                                      /* private_flags */
2753                         NULL,                                   /* sd */
2754                         NULL,                                   /* ea_list */
2755                         &fsp,                                   /* result */
2756                         NULL,                                   /* pinfo */
2757                         NULL, NULL);                            /* create context */
2758
2759                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2760                         TALLOC_FREE(fname);
2761                         TALLOC_FREE(smb_fname);
2762                         continue;
2763                 }
2764
2765                 if (!NT_STATUS_IS_OK(status)) {
2766                         if (open_was_deferred(req->xconn, req->mid)) {
2767                                 /* We have re-scheduled this call. */
2768                                 goto out;
2769                         }
2770                         reply_openerror(req, status);
2771                         goto out;
2772                 }
2773
2774                 break;
2775         }
2776
2777         if (i == 10) {
2778                 /* Collision after 10 times... */
2779                 reply_nterror(req, status);
2780                 goto out;
2781         }
2782
2783         reply_outbuf(req, 1, 0);
2784         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2785
2786         /* the returned filename is relative to the directory */
2787         s = strrchr_m(fsp->fsp_name->base_name, '/');
2788         if (!s) {
2789                 s = fsp->fsp_name->base_name;
2790         } else {
2791                 s++;
2792         }
2793
2794 #if 0
2795         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2796            thing in the byte section. JRA */
2797         SSVALS(p, 0, -1); /* what is this? not in spec */
2798 #endif
2799         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2800             == -1) {
2801                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2802                 goto out;
2803         }
2804
2805         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2806                 SCVAL(req->outbuf, smb_flg,
2807                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2808         }
2809
2810         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2811                 SCVAL(req->outbuf, smb_flg,
2812                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2813         }
2814
2815         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2816         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2817                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2818  out:
2819         TALLOC_FREE(smb_fname);
2820         TALLOC_FREE(wire_name);
2821         END_PROFILE(SMBctemp);
2822         return;
2823 }
2824
2825 /*******************************************************************
2826  Check if a user is allowed to rename a file.
2827 ********************************************************************/
2828
2829 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2830                         uint16_t dirtype)
2831 {
2832         if (!CAN_WRITE(conn)) {
2833                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2834         }
2835
2836         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2837                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2838                 /* Only bother to read the DOS attribute if we might deny the
2839                    rename on the grounds of attribute mismatch. */
2840                 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2841                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2842                         return NT_STATUS_NO_SUCH_FILE;
2843                 }
2844         }
2845
2846         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2847                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2848                         return NT_STATUS_OK;
2849                 }
2850
2851                 /* If no pathnames are open below this
2852                    directory, allow the rename. */
2853
2854                 if (lp_strict_rename(SNUM(conn))) {
2855                         /*
2856                          * Strict rename, check open file db.
2857                          */
2858                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2859                                 return NT_STATUS_ACCESS_DENIED;
2860                         }
2861                 } else if (file_find_subpath(fsp)) {
2862                         /*
2863                          * No strict rename, just look in local process.
2864                          */
2865                         return NT_STATUS_ACCESS_DENIED;
2866                 }
2867                 return NT_STATUS_OK;
2868         }
2869
2870         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2871                 return NT_STATUS_OK;
2872         }
2873
2874         return NT_STATUS_ACCESS_DENIED;
2875 }
2876
2877 /*******************************************************************
2878  * unlink a file with all relevant access checks
2879  *******************************************************************/
2880
2881 static NTSTATUS do_unlink(connection_struct *conn,
2882                         struct smb_request *req,
2883                         struct smb_filename *smb_fname,
2884                         uint32_t dirtype)
2885 {
2886         uint32_t fattr;
2887         files_struct *fsp;
2888         uint32_t dirtype_orig = dirtype;
2889         NTSTATUS status;
2890         int ret;
2891         bool posix_paths = (req != NULL && req->posix_pathnames);
2892
2893         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2894                   smb_fname_str_dbg(smb_fname),
2895                   dirtype));
2896
2897         if (!CAN_WRITE(conn)) {
2898                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2899         }
2900
2901         if (posix_paths) {
2902                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2903         } else {
2904                 ret = SMB_VFS_STAT(conn, smb_fname);
2905         }
2906         if (ret != 0) {
2907                 return map_nt_error_from_unix(errno);
2908         }
2909
2910         fattr = dos_mode(conn, smb_fname);
2911
2912         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2913                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2914         }
2915
2916         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2917         if (!dirtype) {
2918                 return NT_STATUS_NO_SUCH_FILE;
2919         }
2920
2921         if (!dir_check_ftype(fattr, dirtype)) {
2922                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2923                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2924                 }
2925                 return NT_STATUS_NO_SUCH_FILE;
2926         }
2927
2928         if (dirtype_orig & 0x8000) {
2929                 /* These will never be set for POSIX. */
2930                 return NT_STATUS_NO_SUCH_FILE;
2931         }
2932
2933 #if 0
2934         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2935                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2936         }
2937
2938         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2939                 return NT_STATUS_NO_SUCH_FILE;
2940         }
2941
2942         if (dirtype & 0xFF00) {
2943                 /* These will never be set for POSIX. */
2944                 return NT_STATUS_NO_SUCH_FILE;
2945         }
2946
2947         dirtype &= 0xFF;
2948         if (!dirtype) {
2949                 return NT_STATUS_NO_SUCH_FILE;
2950         }
2951
2952         /* Can't delete a directory. */
2953         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2954                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2955         }
2956 #endif
2957
2958 #if 0 /* JRATEST */
2959         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2960                 return NT_STATUS_OBJECT_NAME_INVALID;
2961 #endif /* JRATEST */
2962
2963         /* On open checks the open itself will check the share mode, so
2964            don't do it here as we'll get it wrong. */
2965
2966         status = SMB_VFS_CREATE_FILE
2967                 (conn,                  /* conn */
2968                  req,                   /* req */
2969                  0,                     /* root_dir_fid */
2970                  smb_fname,             /* fname */
2971                  DELETE_ACCESS,         /* access_mask */
2972                  FILE_SHARE_NONE,       /* share_access */
2973                  FILE_OPEN,             /* create_disposition*/
2974                  FILE_NON_DIRECTORY_FILE, /* create_options */
2975                                         /* file_attributes */
2976                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2977                                 FILE_ATTRIBUTE_NORMAL,
2978                  0,                     /* oplock_request */
2979                  NULL,                  /* lease */
2980                  0,                     /* allocation_size */
2981                  0,                     /* private_flags */
2982                  NULL,                  /* sd */
2983                  NULL,                  /* ea_list */
2984                  &fsp,                  /* result */
2985                  NULL,                  /* pinfo */
2986                  NULL, NULL);           /* create context */
2987
2988         if (!NT_STATUS_IS_OK(status)) {
2989                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2990                            nt_errstr(status)));
2991                 return status;
2992         }
2993
2994         status = can_set_delete_on_close(fsp, fattr);
2995         if (!NT_STATUS_IS_OK(status)) {
2996                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2997                         "(%s)\n",
2998                         smb_fname_str_dbg(smb_fname),
2999                         nt_errstr(status)));
3000                 close_file(req, fsp, NORMAL_CLOSE);
3001                 return status;
3002         }
3003
3004         /* The set is across all open files on this dev/inode pair. */
3005         if (!set_delete_on_close(fsp, True,
3006                                 conn->session_info->security_token,
3007                                 conn->session_info->unix_token)) {
3008                 close_file(req, fsp, NORMAL_CLOSE);
3009                 return NT_STATUS_ACCESS_DENIED;
3010         }
3011
3012         return close_file(req, fsp, NORMAL_CLOSE);
3013 }
3014
3015 /****************************************************************************
3016  The guts of the unlink command, split out so it may be called by the NT SMB
3017  code.
3018 ****************************************************************************/
3019
3020 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3021                           uint32_t dirtype, struct smb_filename *smb_fname,
3022                           bool has_wild)
3023 {
3024         char *fname_dir = NULL;
3025         char *fname_mask = NULL;
3026         int count=0;
3027         NTSTATUS status = NT_STATUS_OK;
3028         struct smb_filename *smb_fname_dir = NULL;
3029         TALLOC_CTX *ctx = talloc_tos();
3030
3031         /* Split up the directory from the filename/mask. */
3032         status = split_fname_dir_mask(ctx, smb_fname->base_name,
3033                                       &fname_dir, &fname_mask);
3034         if (!NT_STATUS_IS_OK(status)) {
3035                 goto out;
3036         }
3037
3038         /*
3039          * We should only check the mangled cache
3040          * here if unix_convert failed. This means
3041          * that the path in 'mask' doesn't exist
3042          * on the file system and so we need to look
3043          * for a possible mangle. This patch from
3044          * Tine Smukavec <valentin.smukavec@hermes.si>.
3045          */
3046
3047         if (!VALID_STAT(smb_fname->st) &&
3048             mangle_is_mangled(fname_mask, conn->params)) {
3049                 char *new_mask = NULL;
3050                 mangle_lookup_name_from_8_3(ctx, fname_mask,
3051                                             &new_mask, conn->params);
3052                 if (new_mask) {
3053                         TALLOC_FREE(fname_mask);
3054                         fname_mask = new_mask;
3055                 }
3056         }
3057
3058         if (!has_wild) {
3059
3060                 /*
3061                  * Only one file needs to be unlinked. Append the mask back
3062                  * onto the directory.
3063                  */
3064                 TALLOC_FREE(smb_fname->base_name);
3065                 if (ISDOT(fname_dir)) {
3066                         /* Ensure we use canonical names on open. */
3067                         smb_fname->base_name = talloc_asprintf(smb_fname,
3068                                                         "%s",
3069                                                         fname_mask);
3070                 } else {
3071                         smb_fname->base_name = talloc_asprintf(smb_fname,
3072                                                         "%s/%s",
3073                                                         fname_dir,
3074                                                         fname_mask);
3075                 }
3076                 if (!smb_fname->base_name) {
3077                         status = NT_STATUS_NO_MEMORY;
3078                         goto out;
3079                 }
3080                 if (dirtype == 0) {
3081                         dirtype = FILE_ATTRIBUTE_NORMAL;
3082                 }
3083
3084                 status = check_name(conn, smb_fname);
3085                 if (!NT_STATUS_IS_OK(status)) {
3086                         goto out;
3087                 }
3088
3089                 status = do_unlink(conn, req, smb_fname, dirtype);
3090                 if (!NT_STATUS_IS_OK(status)) {
3091                         goto out;
3092                 }
3093
3094                 count++;
3095         } else {
3096                 struct smb_Dir *dir_hnd = NULL;
3097                 long offset = 0;
3098                 const char *dname = NULL;
3099                 char *talloced = NULL;
3100
3101                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3102                         status = NT_STATUS_OBJECT_NAME_INVALID;
3103                         goto out;
3104                 }
3105                 if (dirtype == 0) {
3106                         dirtype = FILE_ATTRIBUTE_NORMAL;
3107                 }
3108
3109                 if (strequal(fname_mask,"????????.???")) {
3110                         TALLOC_FREE(fname_mask);
3111                         fname_mask = talloc_strdup(ctx, "*");
3112                         if (!fname_mask) {
3113                                 status = NT_STATUS_NO_MEMORY;
3114                                 goto out;
3115                         }
3116                 }
3117
3118                 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3119                                         fname_dir,
3120                                         NULL,
3121                                         NULL,
3122                                         smb_fname->flags);
3123                 if (smb_fname_dir == NULL) {
3124                         status = NT_STATUS_NO_MEMORY;
3125                         goto out;
3126                 }
3127
3128                 status = check_name(conn, smb_fname_dir);
3129                 if (!NT_STATUS_IS_OK(status)) {
3130                         goto out;
3131                 }
3132
3133                 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3134                                   dirtype);
3135                 if (dir_hnd == NULL) {
3136                         status = map_nt_error_from_unix(errno);
3137                         goto out;
3138                 }
3139
3140                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3141                    the pattern matches against the long name, otherwise the short name 
3142                    We don't implement this yet XXXX
3143                 */
3144
3145                 status = NT_STATUS_NO_SUCH_FILE;
3146
3147                 while ((dname = ReadDirName(dir_hnd, &offset,
3148                                             &smb_fname->st, &talloced))) {
3149                         TALLOC_CTX *frame = talloc_stackframe();
3150
3151                         if (!is_visible_file(conn, fname_dir, dname,
3152                                              &smb_fname->st, true)) {
3153                                 TALLOC_FREE(frame);
3154                                 TALLOC_FREE(talloced);
3155                                 continue;
3156                         }
3157
3158                         /* Quick check for "." and ".." */
3159                         if (ISDOT(dname) || ISDOTDOT(dname)) {
3160                                 TALLOC_FREE(frame);
3161                                 TALLOC_FREE(talloced);
3162                                 continue;
3163                         }
3164
3165                         if(!mask_match(dname, fname_mask,
3166                                        conn->case_sensitive)) {
3167                                 TALLOC_FREE(frame);
3168                                 TALLOC_FREE(talloced);
3169                                 continue;
3170                         }
3171
3172                         TALLOC_FREE(smb_fname->base_name);
3173                         if (ISDOT(fname_dir)) {
3174                                 /* Ensure we use canonical names on open. */
3175                                 smb_fname->base_name =
3176                                         talloc_asprintf(smb_fname, "%s",
3177                                                 dname);
3178                         } else {
3179                                 smb_fname->base_name =
3180                                         talloc_asprintf(smb_fname, "%s/%s",
3181                                                 fname_dir, dname);
3182                         }
3183
3184                         if (!smb_fname->base_name) {
3185                                 TALLOC_FREE(dir_hnd);
3186                                 status = NT_STATUS_NO_MEMORY;
3187                                 TALLOC_FREE(frame);
3188                                 TALLOC_FREE(talloced);
3189                                 goto out;
3190                         }
3191
3192                         status = check_name(conn, smb_fname);
3193                         if (!NT_STATUS_IS_OK(status)) {
3194                                 TALLOC_FREE(dir_hnd);
3195                                 TALLOC_FREE(frame);
3196                                 TALLOC_FREE(talloced);
3197                                 goto out;
3198                         }
3199
3200                         status = do_unlink(conn, req, smb_fname, dirtype);
3201                         if (!NT_STATUS_IS_OK(status)) {
3202                                 TALLOC_FREE(dir_hnd);
3203                                 TALLOC_FREE(frame);
3204                                 TALLOC_FREE(talloced);
3205                                 goto out;
3206                         }
3207
3208                         count++;
3209                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3210                                  smb_fname->base_name));
3211
3212                         TALLOC_FREE(frame);
3213                         TALLOC_FREE(talloced);
3214                 }
3215                 TALLOC_FREE(dir_hnd);
3216         }
3217
3218         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3219                 status = map_nt_error_from_unix(errno);
3220         }
3221
3222  out:
3223         TALLOC_FREE(smb_fname_dir);
3224         TALLOC_FREE(fname_dir);
3225         TALLOC_FREE(fname_mask);
3226         return status;
3227 }
3228
3229 /****************************************************************************
3230  Reply to a unlink
3231 ****************************************************************************/
3232
3233 void reply_unlink(struct smb_request *req)
3234 {
3235         connection_struct *conn = req->conn;
3236         char *name = NULL;
3237         struct smb_filename *smb_fname = NULL;
3238         uint32_t dirtype;
3239         NTSTATUS status;
3240         bool path_contains_wcard = False;
3241         uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3242                         ucf_flags_from_smb_request(req);
3243         TALLOC_CTX *ctx = talloc_tos();
3244
3245         START_PROFILE(SMBunlink);
3246
3247         if (req->wct < 1) {
3248                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3249                 goto out;
3250         }
3251
3252         dirtype = SVAL(req->vwv+0, 0);
3253
3254         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3255                                   STR_TERMINATE, &status,
3256                                   &path_contains_wcard);
3257         if (!NT_STATUS_IS_OK(status)) {
3258                 reply_nterror(req, status);
3259                 goto out;
3260         }
3261
3262         status = filename_convert(ctx, conn,
3263                                   name,
3264                                   ucf_flags,
3265                                   NULL,
3266                                   &path_contains_wcard,
3267                                   &smb_fname);
3268         if (!NT_STATUS_IS_OK(status)) {
3269                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3270                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3271                                         ERRSRV, ERRbadpath);
3272                         goto out;
3273                 }
3274                 reply_nterror(req, status);
3275                 goto out;
3276         }
3277
3278         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3279
3280         status = unlink_internals(conn, req, dirtype, smb_fname,
3281                                   path_contains_wcard);
3282         if (!NT_STATUS_IS_OK(status)) {
3283                 if (open_was_deferred(req->xconn, req->mid)) {
3284                         /* We have re-scheduled this call. */
3285                         goto out;
3286                 }
3287                 reply_nterror(req, status);
3288                 goto out;
3289         }
3290
3291         reply_outbuf(req, 0, 0);
3292  out:
3293         TALLOC_FREE(smb_fname);
3294         END_PROFILE(SMBunlink);
3295         return;
3296 }
3297
3298 /****************************************************************************
3299  Fail for readbraw.
3300 ****************************************************************************/
3301
3302 static void fail_readraw(void)
3303 {
3304         const char *errstr = talloc_asprintf(talloc_tos(),
3305                         "FAIL ! reply_readbraw: socket write fail (%s)",
3306                         strerror(errno));
3307         if (!errstr) {
3308                 errstr = "";
3309         }
3310         exit_server_cleanly(errstr);
3311 }
3312
3313 /****************************************************************************
3314  Fake (read/write) sendfile. Returns -1 on read or write fail.
3315 ****************************************************************************/
3316
3317 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3318                       off_t startpos, size_t nread)
3319 {
3320         size_t bufsize;
3321         size_t tosend = nread;
3322         char *buf;
3323
3324         if (nread == 0) {
3325                 return 0;
3326         }
3327
3328         bufsize = MIN(nread, 65536);
3329
3330         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3331                 return -1;
3332         }
3333
3334         while (tosend > 0) {
3335                 ssize_t ret;
3336                 size_t cur_read;
3337
3338                 cur_read = MIN(tosend, bufsize);
3339                 ret = read_file(fsp,buf,startpos,cur_read);
3340                 if (ret == -1) {
3341                         SAFE_FREE(buf);
3342                         return -1;
3343                 }
3344
3345                 /* If we had a short read, fill with zeros. */
3346                 if (ret < cur_read) {
3347                         memset(buf + ret, '\0', cur_read - ret);
3348                 }
3349
3350                 ret = write_data(xconn->transport.sock, buf, cur_read);
3351                 if (ret != cur_read) {
3352                         int saved_errno = errno;
3353                         /*
3354                          * Try and give an error message saying what
3355                          * client failed.
3356                          */
3357                         DEBUG(0, ("write_data failed for client %s. "
3358                                   "Error %s\n",
3359                                   smbXsrv_connection_dbg(xconn),
3360                                   strerror(saved_errno)));
3361                         SAFE_FREE(buf);
3362                         errno = saved_errno;
3363                         return -1;
3364                 }
3365                 tosend -= cur_read;
3366                 startpos += cur_read;
3367         }
3368
3369         SAFE_FREE(buf);
3370         return (ssize_t)nread;
3371 }
3372
3373 /****************************************************************************
3374  Deal with the case of sendfile reading less bytes from the file than
3375  requested. Fill with zeros (all we can do). Returns 0 on success
3376 ****************************************************************************/
3377
3378 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3379                             files_struct *fsp,
3380                             ssize_t nread,
3381                             size_t headersize,
3382                             size_t smb_maxcnt)
3383 {
3384 #define SHORT_SEND_BUFSIZE 1024
3385         if (nread < headersize) {
3386                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3387                         "header for file %s (%s). Terminating\n",
3388                         fsp_str_dbg(fsp), strerror(errno)));
3389                 return -1;
3390         }
3391
3392         nread -= headersize;
3393
3394         if (nread < smb_maxcnt) {
3395                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3396                 if (!buf) {
3397                         DEBUG(0,("sendfile_short_send: malloc failed "
3398                                 "for file %s (%s). Terminating\n",
3399                                 fsp_str_dbg(fsp), strerror(errno)));
3400                         return -1;
3401                 }
3402
3403                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3404                         "with zeros !\n", fsp_str_dbg(fsp)));
3405
3406                 while (nread < smb_maxcnt) {
3407                         /*
3408                          * We asked for the real file size and told sendfile
3409                          * to not go beyond the end of the file. But it can
3410                          * happen that in between our fstat call and the
3411                          * sendfile call the file was truncated. This is very
3412                          * bad because we have already announced the larger
3413                          * number of bytes to the client.
3414                          *
3415                          * The best we can do now is to send 0-bytes, just as
3416                          * a read from a hole in a sparse file would do.
3417                          *
3418                          * This should happen rarely enough that I don't care
3419                          * about efficiency here :-)
3420                          */
3421                         size_t to_write;
3422                         ssize_t ret;
3423
3424                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3425                         ret = write_data(xconn->transport.sock, buf, to_write);
3426                         if (ret != to_write) {
3427                                 int saved_errno = errno;
3428                                 /*
3429                                  * Try and give an error message saying what
3430                                  * client failed.
3431                                  */
3432                                 DEBUG(0, ("write_data failed for client %s. "
3433                                           "Error %s\n",
3434                                           smbXsrv_connection_dbg(xconn),
3435                                           strerror(saved_errno)));
3436                                 errno = saved_errno;
3437                                 return -1;
3438                         }
3439                         nread += to_write;
3440                 }
3441                 SAFE_FREE(buf);
3442         }
3443
3444         return 0;
3445 }
3446
3447 /****************************************************************************
3448  Return a readbraw error (4 bytes of zero).
3449 ****************************************************************************/
3450
3451 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3452 {
3453         char header[4];
3454
3455         SIVAL(header,0,0);
3456
3457         smbd_lock_socket(xconn);
3458         if (write_data(xconn->transport.sock,header,4) != 4) {
3459                 int saved_errno = errno;
3460                 /*
3461                  * Try and give an error message saying what
3462                  * client failed.
3463                  */
3464                 DEBUG(0, ("write_data failed for client %s. "
3465                           "Error %s\n",
3466                           smbXsrv_connection_dbg(xconn),
3467                           strerror(saved_errno)));
3468                 errno = saved_errno;
3469
3470                 fail_readraw();
3471         }
3472         smbd_unlock_socket(xconn);
3473 }
3474
3475 /****************************************************************************
3476  Use sendfile in readbraw.
3477 ****************************************************************************/
3478
3479 static void send_file_readbraw(connection_struct *conn,
3480                                struct smb_request *req,
3481                                files_struct *fsp,
3482                                off_t startpos,
3483                                size_t nread,
3484                                ssize_t mincount)
3485 {
3486         struct smbXsrv_connection *xconn = req->xconn;
3487         char *outbuf = NULL;
3488         ssize_t ret=0;
3489
3490         /*
3491          * We can only use sendfile on a non-chained packet 
3492          * but we can use on a non-oplocked file. tridge proved this
3493          * on a train in Germany :-). JRA.
3494          * reply_readbraw has already checked the length.
3495          */
3496
3497         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3498             (fsp->wcp == NULL) &&
3499             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3500                 ssize_t sendfile_read = -1;
3501                 char header[4];
3502                 DATA_BLOB header_blob;
3503
3504                 _smb_setlen(header,nread);
3505                 header_blob = data_blob_const(header, 4);
3506
3507                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3508                                                  &header_blob, startpos,
3509                                                  nread);
3510                 if (sendfile_read == -1) {
3511                         /* Returning ENOSYS means no data at all was sent.
3512                          * Do this as a normal read. */
3513                         if (errno == ENOSYS) {
3514                                 goto normal_readbraw;
3515                         }
3516
3517                         /*
3518                          * Special hack for broken Linux with no working sendfile. If we
3519                          * return EINTR we sent the header but not the rest of the data.
3520                          * Fake this up by doing read/write calls.
3521                          */
3522                         if (errno == EINTR) {
3523                                 /* Ensure we don't do this again. */
3524                                 set_use_sendfile(SNUM(conn), False);
3525                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3526
3527                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3528                                         DEBUG(0,("send_file_readbraw: "
3529                                                  "fake_sendfile failed for "
3530                                                  "file %s (%s).\n",
3531                                                  fsp_str_dbg(fsp),
3532                                                  strerror(errno)));
3533                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3534                                 }
3535                                 return;
3536                         }
3537
3538                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3539                                  "file %s (%s). Terminating\n",
3540                                  fsp_str_dbg(fsp), strerror(errno)));
3541                         exit_server_cleanly("send_file_readbraw sendfile failed");
3542                 } else if (sendfile_read == 0) {
3543                         /*
3544                          * Some sendfile implementations return 0 to indicate
3545                          * that there was a short read, but nothing was
3546                          * actually written to the socket.  In this case,
3547                          * fallback to the normal read path so the header gets
3548                          * the correct byte count.
3549                          */
3550                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3551                                   "bytes falling back to the normal read: "
3552                                   "%s\n", fsp_str_dbg(fsp)));
3553                         goto normal_readbraw;
3554                 }
3555
3556                 /* Deal with possible short send. */
3557                 if (sendfile_read != 4+nread) {
3558                         ret = sendfile_short_send(xconn, fsp,
3559                                                   sendfile_read, 4, nread);
3560                         if (ret == -1) {
3561                                 fail_readraw();
3562                         }
3563                 }
3564                 return;
3565         }
3566
3567 normal_readbraw:
3568
3569         outbuf = talloc_array(NULL, char, nread+4);
3570         if (!outbuf) {
3571                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3572                         (unsigned)(nread+4)));
3573                 reply_readbraw_error(xconn);
3574                 return;
3575         }
3576
3577         if (nread > 0) {
3578                 ret = read_file(fsp,outbuf+4,startpos,nread);
3579 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3580                 if (ret < mincount)
3581                         ret = 0;
3582 #else
3583                 if (ret < nread)
3584                         ret = 0;
3585 #endif
3586         }
3587
3588         _smb_setlen(outbuf,ret);
3589         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3590                 int saved_errno = errno;
3591                 /*
3592                  * Try and give an error message saying what
3593                  * client failed.
3594                  */
3595                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3596                           smbXsrv_connection_dbg(xconn),
3597                           strerror(saved_errno)));
3598                 errno = saved_errno;
3599
3600                 fail_readraw();
3601         }
3602
3603         TALLOC_FREE(outbuf);
3604 }
3605
3606 /****************************************************************************
3607  Reply to a readbraw (core+ protocol).
3608 ****************************************************************************/
3609
3610 void reply_readbraw(struct smb_request *req)
3611 {
3612         connection_struct *conn = req->conn;
3613         struct smbXsrv_connection *xconn = req->xconn;
3614         ssize_t maxcount,mincount;
3615         size_t nread = 0;
3616         off_t startpos;
3617         files_struct *fsp;
3618         struct lock_struct lock;
3619         off_t size = 0;
3620
3621         START_PROFILE(SMBreadbraw);
3622
3623         if (srv_is_signing_active(xconn) || req->encrypted) {
3624                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3625                         "raw reads/writes are disallowed.");
3626         }
3627
3628         if (req->wct < 8) {
3629                 reply_readbraw_error(xconn);
3630                 END_PROFILE(SMBreadbraw);
3631                 return;
3632         }
3633
3634         if (xconn->smb1.echo_handler.trusted_fde) {
3635                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3636                          "'async smb echo handler = yes'\n"));
3637                 reply_readbraw_error(xconn);
3638                 END_PROFILE(SMBreadbraw);
3639                 return;
3640         }
3641
3642         /*
3643          * Special check if an oplock break has been issued
3644          * and the readraw request croses on the wire, we must
3645          * return a zero length response here.
3646          */
3647
3648         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3649
3650         /*
3651          * We have to do a check_fsp by hand here, as
3652          * we must always return 4 zero bytes on error,
3653          * not a NTSTATUS.
3654          */
3655
3656         if (!fsp || !conn || conn != fsp->conn ||
3657                         req->vuid != fsp->vuid ||
3658                         fsp->is_directory || fsp->fh->fd == -1) {
3659                 /*
3660                  * fsp could be NULL here so use the value from the packet. JRA.
3661                  */
3662                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3663                         "- cache prime?\n",
3664                         (int)SVAL(req->vwv+0, 0)));
3665                 reply_readbraw_error(xconn);
3666                 END_PROFILE(SMBreadbraw);
3667                 return;
3668         }
3669
3670         /* Do a "by hand" version of CHECK_READ. */
3671         if (!(fsp->can_read ||
3672                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3673                                 (fsp->access_mask & FILE_EXECUTE)))) {
3674                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3675                                 (int)SVAL(req->vwv+0, 0)));
3676                 reply_readbraw_error(xconn);
3677                 END_PROFILE(SMBreadbraw);
3678                 return;
3679         }
3680
3681         flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3682
3683         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3684         if(req->wct == 10) {
3685                 /*
3686                  * This is a large offset (64 bit) read.
3687                  */
3688
3689                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3690
3691                 if(startpos < 0) {
3692                         DEBUG(0,("reply_readbraw: negative 64 bit "
3693                                 "readraw offset (%.0f) !\n",
3694                                 (double)startpos ));
3695                         reply_readbraw_error(xconn);
3696                         END_PROFILE(SMBreadbraw);
3697                         return;
3698                 }
3699         }
3700
3701         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3702         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3703
3704         /* ensure we don't overrun the packet size */
3705         maxcount = MIN(65535,maxcount);
3706
3707         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3708             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3709             &lock);
3710
3711         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3712                 reply_readbraw_error(xconn);
3713                 END_PROFILE(SMBreadbraw);
3714                 return;
3715         }
3716
3717         if (fsp_stat(fsp) == 0) {
3718                 size = fsp->fsp_name->st.st_ex_size;
3719         }
3720
3721         if (startpos >= size) {
3722                 nread = 0;
3723         } else {
3724                 nread = MIN(maxcount,(size - startpos));
3725         }
3726
3727 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3728         if (nread < mincount)
3729                 nread = 0;
3730 #endif
3731
3732         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3733                 "min=%lu nread=%lu\n",
3734                 fsp_fnum_dbg(fsp), (double)startpos,
3735                 (unsigned long)maxcount,
3736                 (unsigned long)mincount,
3737                 (unsigned long)nread ) );
3738
3739         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3740
3741         DEBUG(5,("reply_readbraw finished\n"));
3742
3743         END_PROFILE(SMBreadbraw);
3744         return;
3745 }
3746
3747 #undef DBGC_CLASS
3748 #define DBGC_CLASS DBGC_LOCKING
3749
3750 /****************************************************************************
3751  Reply to a lockread (core+ protocol).
3752 ****************************************************************************/
3753
3754 static void reply_lockread_locked(struct tevent_req *subreq);
3755
3756 void reply_lockread(struct smb_request *req)
3757 {
3758         struct tevent_req *subreq = NULL;
3759         connection_struct *conn = req->conn;
3760         files_struct *fsp;
3761         struct smbd_lock_element *lck = NULL;
3762
3763         START_PROFILE(SMBlockread);
3764
3765         if (req->wct < 5) {
3766                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767                 END_PROFILE(SMBlockread);
3768                 return;
3769         }
3770
3771         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3772
3773         if (!check_fsp(conn, req, fsp)) {
3774                 END_PROFILE(SMBlockread);
3775                 return;
3776         }
3777
3778         if (!CHECK_READ(fsp,req)) {
3779                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3780                 END_PROFILE(SMBlockread);
3781                 return;
3782         }
3783
3784         lck = talloc(req, struct smbd_lock_element);
3785         if (lck == NULL) {
3786                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3787                 END_PROFILE(SMBlockread);
3788                 return;
3789         }
3790
3791         /*
3792          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3793          * protocol request that predates the read/write lock concept. 
3794          * Thus instead of asking for a read lock here we need to ask
3795          * for a write lock. JRA.
3796          * Note that the requested lock size is unaffected by max_send.
3797          */
3798
3799         *lck = (struct smbd_lock_element) {
3800                 .smblctx = req->smbpid,
3801                 .brltype = WRITE_LOCK,
3802                 .count = SVAL(req->vwv+1, 0),
3803                 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3804         };
3805
3806         subreq = smbd_smb1_do_locks_send(
3807                 fsp,
3808                 req->sconn->ev_ctx,
3809                 &req,
3810                 fsp,
3811                 0,
3812                 false,          /* large_offset */
3813                 WINDOWS_LOCK,
3814                 1,
3815                 lck);
3816         if (subreq == NULL) {
3817                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3818                 END_PROFILE(SMBlockread);
3819                 return;
3820         }
3821         tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3822         END_PROFILE(SMBlockread);
3823 }
3824
3825 static void reply_lockread_locked(struct tevent_req *subreq)
3826 {
3827         struct smb_request *req = NULL;
3828         ssize_t nread = -1;
3829         char *data = NULL;
3830         NTSTATUS status;
3831         bool ok;
3832         off_t startpos;
3833         size_t numtoread, maxtoread;
3834         struct files_struct *fsp = NULL;
3835         char *p = NULL;
3836
3837         START_PROFILE(SMBlockread);
3838
3839         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3840         SMB_ASSERT(ok);
3841
3842         status = smbd_smb1_do_locks_recv(subreq);
3843         TALLOC_FREE(subreq);
3844
3845         if (!NT_STATUS_IS_OK(status)) {
3846                 reply_nterror(req, status);
3847                 goto send;
3848         }
3849
3850         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3851         if (fsp == NULL) {
3852                 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3853                 goto send;
3854         }
3855
3856         numtoread = SVAL(req->vwv+1, 0);
3857         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3858
3859         /*
3860          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3861          */
3862         maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3863
3864         if (numtoread > maxtoread) {
3865                 DBG_WARNING("requested read size (%zu) is greater than "
3866                             "maximum allowed (%zu/%d). "
3867                             "Returning short read of maximum allowed for "
3868                             "compatibility with Windows 2000.\n",
3869                             numtoread,
3870                             maxtoread,
3871                             req->xconn->smb1.sessions.max_send);
3872                 numtoread = maxtoread;
3873         }
3874
3875         reply_outbuf(req, 5, numtoread + 3);
3876
3877         data = smb_buf(req->outbuf) + 3;
3878
3879         nread = read_file(fsp,data,startpos,numtoread);
3880
3881         if (nread < 0) {
3882                 reply_nterror(req, map_nt_error_from_unix(errno));
3883                 goto send;
3884         }
3885
3886         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3887
3888         SSVAL(req->outbuf,smb_vwv0,nread);
3889         SSVAL(req->outbuf,smb_vwv5,nread+3);
3890         p = smb_buf(req->outbuf);
3891         SCVAL(p,0,0); /* pad byte. */
3892         SSVAL(p,1,nread);
3893
3894         DEBUG(3,("lockread %s num=%d nread=%d\n",
3895                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3896
3897 send:
3898         ok = srv_send_smb(req->xconn,
3899                           (char *)req->outbuf,
3900                           true,
3901                           req->seqnum+1,
3902                           IS_CONN_ENCRYPTED(req->conn),
3903                           NULL);
3904         if (!ok) {
3905                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
3906         }
3907         TALLOC_FREE(req);
3908         END_PROFILE(SMBlockread);
3909         return;
3910 }
3911
3912 #undef DBGC_CLASS
3913 #define DBGC_CLASS DBGC_ALL
3914
3915 /****************************************************************************
3916  Reply to a read.
3917 ****************************************************************************/
3918
3919 void reply_read(struct smb_request *req)
3920 {
3921         connection_struct *conn = req->conn;
3922         size_t numtoread;
3923         size_t maxtoread;
3924         ssize_t nread = 0;
3925         char *data;
3926         off_t startpos;
3927         files_struct *fsp;
3928         struct lock_struct lock;
3929         struct smbXsrv_connection *xconn = req->xconn;
3930
3931         START_PROFILE(SMBread);
3932
3933         if (req->wct < 3) {
3934                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3935                 END_PROFILE(SMBread);
3936                 return;
3937         }
3938
3939         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3940
3941         if (!check_fsp(conn, req, fsp)) {
3942                 END_PROFILE(SMBread);
3943                 return;
3944         }
3945
3946         if (!CHECK_READ(fsp,req)) {
3947                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3948                 END_PROFILE(SMBread);
3949                 return;
3950         }
3951
3952         numtoread = SVAL(req->vwv+1, 0);
3953         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3954
3955         /*
3956          * The requested read size cannot be greater than max_send. JRA.
3957          */
3958         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3959
3960         if (numtoread > maxtoread) {
3961                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3962 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3963                         (unsigned int)numtoread, (unsigned int)maxtoread,
3964                         (unsigned int)xconn->smb1.sessions.max_send));
3965                 numtoread = maxtoread;
3966         }
3967
3968         reply_outbuf(req, 5, numtoread+3);
3969
3970         data = smb_buf(req->outbuf) + 3;
3971
3972         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3973             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3974             &lock);
3975
3976         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3977                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3978                 END_PROFILE(SMBread);
3979                 return;
3980         }
3981
3982         if (numtoread > 0)
3983                 nread = read_file(fsp,data,startpos,numtoread);
3984
3985         if (nread < 0) {
3986                 reply_nterror(req, map_nt_error_from_unix(errno));
3987                 goto out;
3988         }
3989
3990         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3991
3992         SSVAL(req->outbuf,smb_vwv0,nread);
3993         SSVAL(req->outbuf,smb_vwv5,nread+3);
3994         SCVAL(smb_buf(req->outbuf),0,1);
3995         SSVAL(smb_buf(req->outbuf),1,nread);
3996
3997         DEBUG(3, ("read %s num=%d nread=%d\n",
3998                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3999
4000 out:
4001         END_PROFILE(SMBread);
4002         return;
4003 }
4004
4005 /****************************************************************************
4006  Setup readX header.
4007 ****************************************************************************/
4008
4009 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4010 {
4011         size_t outsize;
4012
4013         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4014                                   False);
4015
4016         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4017
4018         SCVAL(outbuf,smb_vwv0,0xFF);
4019         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4020         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4021         SSVAL(outbuf,smb_vwv6,
4022               (smb_wct - 4)     /* offset from smb header to wct */
4023               + 1               /* the wct field */
4024               + 12 * sizeof(uint16_t) /* vwv */
4025               + 2               /* the buflen field */
4026               + 1);             /* padding byte */
4027         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4028         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4029         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4030         _smb_setlen_large(outbuf,
4031                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4032         return outsize;
4033 }
4034
4035 /****************************************************************************
4036  Reply to a read and X - possibly using sendfile.
4037 ****************************************************************************/
4038
4039 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4040                             files_struct *fsp, off_t startpos,
4041                             size_t smb_maxcnt)
4042 {
4043         struct smbXsrv_connection *xconn = req->xconn;
4044         ssize_t nread = -1;
4045         struct lock_struct lock;
4046         int saved_errno = 0;
4047
4048         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4049             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4050             &lock);
4051
4052         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4053                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4054                 return;
4055         }
4056
4057         /*
4058          * We can only use sendfile on a non-chained packet
4059          * but we can use on a non-oplocked file. tridge proved this
4060          * on a train in Germany :-). JRA.
4061          */
4062
4063         if (!req_is_in_chain(req) &&
4064             !req->encrypted &&
4065             (fsp->base_fsp == NULL) &&
4066             (fsp->wcp == NULL) &&
4067             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4068                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4069                 DATA_BLOB header;
4070
4071                 if(fsp_stat(fsp) == -1) {
4072                         reply_nterror(req, map_nt_error_from_unix(errno));
4073                         goto out;
4074                 }
4075
4076                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4077                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4078                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4079                         /*
4080                          * We already know that we would do a short read, so don't
4081                          * try the sendfile() path.
4082                          */
4083                         goto nosendfile_read;
4084                 }
4085
4086                 /*
4087                  * Set up the packet header before send. We
4088                  * assume here the sendfile will work (get the
4089                  * correct amount of data).
4090                  */
4091
4092                 header = data_blob_const(headerbuf, sizeof(headerbuf));
4093
4094                 construct_reply_common_req(req, (char *)headerbuf);
4095                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4096
4097                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4098                                          startpos, smb_maxcnt);
4099                 if (nread == -1) {
4100                         saved_errno = errno;
4101
4102                         /* Returning ENOSYS means no data at all was sent.
4103                            Do this as a normal read. */
4104                         if (errno == ENOSYS) {
4105                                 goto normal_read;
4106                         }
4107
4108                         /*
4109                          * Special hack for broken Linux with no working sendfile. If we
4110                          * return EINTR we sent the header but not the rest of the data.
4111                          * Fake this up by doing read/write calls.
4112                          */
4113
4114                         if (errno == EINTR) {
4115                                 /* Ensure we don't do this again. */
4116                                 set_use_sendfile(SNUM(conn), False);
4117                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4118                                 nread = fake_sendfile(xconn, fsp, startpos,
4119                                                       smb_maxcnt);
4120                                 if (nread == -1) {
4121                                         saved_errno = errno;
4122                                         DEBUG(0,("send_file_readX: "
4123                                                  "fake_sendfile failed for "
4124                                                  "file %s (%s) for client %s. "
4125                                                  "Terminating\n",
4126                                                  fsp_str_dbg(fsp),
4127                                                  smbXsrv_connection_dbg(xconn),
4128                                                  strerror(saved_errno)));
4129                                         errno = saved_errno;
4130                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4131                                 }
4132                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4133                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4134                                 /* No outbuf here means successful sendfile. */
4135                                 goto out;
4136                         }
4137
4138                         DEBUG(0,("send_file_readX: sendfile failed for file "
4139                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4140                                  strerror(errno)));
4141                         exit_server_cleanly("send_file_readX sendfile failed");
4142                 } else if (nread == 0) {
4143                         /*
4144                          * Some sendfile implementations return 0 to indicate
4145                          * that there was a short read, but nothing was
4146                          * actually written to the socket.  In this case,
4147                          * fallback to the normal read path so the header gets
4148                          * the correct byte count.
4149                          */
4150                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4151                                   "falling back to the normal read: %s\n",
4152                                   fsp_str_dbg(fsp)));
4153                         goto normal_read;
4154                 }
4155
4156                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4157                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4158
4159                 /* Deal with possible short send. */
4160                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4161                         ssize_t ret;
4162
4163                         ret = sendfile_short_send(xconn, fsp, nread,
4164                                                   sizeof(headerbuf), smb_maxcnt);
4165                         if (ret == -1) {
4166                                 const char *r;
4167                                 r = "send_file_readX: sendfile_short_send failed";
4168                                 DEBUG(0,("%s for file %s (%s).\n",
4169                                          r, fsp_str_dbg(fsp), strerror(errno)));
4170                                 exit_server_cleanly(r);
4171                         }
4172                 }
4173                 /* No outbuf here means successful sendfile. */
4174                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4175                 SMB_PERFCOUNT_END(&req->pcd);
4176                 goto out;
4177         }
4178
4179 normal_read:
4180
4181         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4182                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4183                 ssize_t ret;
4184
4185                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4186                     (startpos > fsp->fsp_name->st.st_ex_size) ||
4187                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4188                         /*
4189                          * We already know that we would do a short
4190                          * read, so don't try the sendfile() path.
4191                          */
4192                         goto nosendfile_read;
4193                 }
4194
4195                 construct_reply_common_req(req, (char *)headerbuf);
4196                 setup_readX_header((char *)headerbuf, smb_maxcnt);
4197
4198                 /* Send out the header. */
4199                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4200                                  sizeof(headerbuf));
4201                 if (ret != sizeof(headerbuf)) {
4202                         saved_errno = errno;
4203                         /*
4204                          * Try and give an error message saying what
4205                          * client failed.
4206                          */
4207                         DEBUG(0,("send_file_readX: write_data failed for file "
4208                                  "%s (%s) for client %s. Terminating\n",
4209                                  fsp_str_dbg(fsp),
4210                                  smbXsrv_connection_dbg(xconn),
4211                                  strerror(saved_errno)));
4212                         errno = saved_errno;
4213                         exit_server_cleanly("send_file_readX sendfile failed");
4214                 }
4215                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4216                 if (nread == -1) {
4217                         saved_errno = errno;
4218                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4219                                  "%s (%s) for client %s. Terminating\n",
4220                                  fsp_str_dbg(fsp),
4221                                  smbXsrv_connection_dbg(xconn),
4222                                  strerror(saved_errno)));
4223                         errno = saved_errno;
4224                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4225                 }
4226                 goto out;
4227         }
4228
4229 nosendfile_read:
4230
4231         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4232         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4233         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4234
4235         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4236                           startpos, smb_maxcnt);
4237         saved_errno = errno;
4238
4239         if (nread < 0) {
4240                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4241                 return;
4242         }
4243
4244         setup_readX_header((char *)req->outbuf, nread);
4245
4246         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4247                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4248         return;
4249
4250 out:
4251         TALLOC_FREE(req->outbuf);
4252         return;
4253 }
4254
4255 /****************************************************************************
4256  Work out how much space we have for a read return.
4257 ****************************************************************************/
4258
4259 static size_t calc_max_read_pdu(const struct smb_request *req)
4260 {
4261         struct smbXsrv_connection *xconn = req->xconn;
4262
4263         if (xconn->protocol < PROTOCOL_NT1) {
4264                 return xconn->smb1.sessions.max_send;
4265         }
4266
4267         if (!lp_large_readwrite()) {
4268                 return xconn->smb1.sessions.max_send;
4269         }
4270
4271         if (req_is_in_chain(req)) {
4272                 return xconn->smb1.sessions.max_send;
4273         }
4274
4275         if (req->encrypted) {
4276                 /*
4277                  * Don't take encrypted traffic up to the
4278                  * limit. There are padding considerations
4279                  * that make that tricky.
4280                  */
4281                 return xconn->smb1.sessions.max_send;
4282         }
4283
4284         if (srv_is_signing_active(xconn)) {
4285                 return 0x1FFFF;
4286         }
4287
4288         if (!lp_unix_extensions()) {
4289                 return 0x1FFFF;
4290         }
4291
4292         /*
4293          * We can do ultra-large POSIX reads.
4294          */
4295         return 0xFFFFFF;
4296 }
4297
4298 /****************************************************************************
4299  Calculate how big a read can be. Copes with all clients. It's always
4300  safe to return a short read - Windows does this.
4301 ****************************************************************************/
4302
4303 static size_t calc_read_size(const struct smb_request *req,
4304                              size_t upper_size,
4305                              size_t lower_size)
4306 {
4307         struct smbXsrv_connection *xconn = req->xconn;
4308         size_t max_pdu = calc_max_read_pdu(req);
4309         size_t total_size = 0;
4310         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4311         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4312
4313         /*
4314          * Windows explicitly ignores upper size of 0xFFFF.
4315          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4316          * We must do the same as these will never fit even in
4317          * an extended size NetBIOS packet.
4318          */
4319         if (upper_size == 0xFFFF) {
4320                 upper_size = 0;
4321         }
4322
4323         if (xconn->protocol < PROTOCOL_NT1) {
4324                 upper_size = 0;
4325         }
4326
4327         total_size = ((upper_size<<16) | lower_size);
4328
4329         /*
4330          * LARGE_READX test shows it's always safe to return
4331          * a short read. Windows does so.
4332          */
4333         return MIN(total_size, max_len);
4334 }
4335
4336 /****************************************************************************
4337  Reply to a read and X.
4338 ****************************************************************************/
4339
4340 void reply_read_and_X(struct smb_request *req)
4341 {
4342         connection_struct *conn = req->conn;
4343         files_struct *fsp;
4344         off_t startpos;
4345         size_t smb_maxcnt;
4346         size_t upper_size;
4347         bool big_readX = False;
4348 #if 0
4349         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4350 #endif
4351
4352         START_PROFILE(SMBreadX);
4353
4354         if ((req->wct != 10) && (req->wct != 12)) {
4355                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4356                 return;
4357         }
4358
4359         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4360         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4361         smb_maxcnt = SVAL(req->vwv+5, 0);
4362
4363         /* If it's an IPC, pass off the pipe handler. */
4364         if (IS_IPC(conn)) {
4365                 reply_pipe_read_and_X(req);
4366                 END_PROFILE(SMBreadX);
4367                 return;
4368         }
4369
4370         if (!check_fsp(conn, req, fsp)) {
4371                 END_PROFILE(SMBreadX);
4372                 return;
4373         }
4374
4375         if (!CHECK_READ(fsp,req)) {
4376                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4377                 END_PROFILE(SMBreadX);
4378                 return;
4379         }
4380
4381         upper_size = SVAL(req->vwv+7, 0);
4382         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4383         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4384                 /*
4385                  * This is a heuristic to avoid keeping large
4386                  * outgoing buffers around over long-lived aio
4387                  * requests.
4388                  */
4389                 big_readX = True;
4390         }
4391
4392         if (req->wct == 12) {
4393                 /*
4394                  * This is a large offset (64 bit) read.
4395                  */
4396                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4397
4398         }
4399
4400         if (!big_readX) {
4401                 NTSTATUS status = schedule_aio_read_and_X(conn,
4402                                         req,
4403                                         fsp,
4404                                         startpos,
4405                                         smb_maxcnt);
4406                 if (NT_STATUS_IS_OK(status)) {
4407                         /* Read scheduled - we're done. */
4408                         goto out;
4409                 }
4410                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4411                         /* Real error - report to client. */
4412                         END_PROFILE(SMBreadX);
4413                         reply_nterror(req, status);
4414                         return;
4415                 }
4416                 /* NT_STATUS_RETRY - fall back to sync read. */
4417         }
4418
4419         smbd_lock_socket(req->xconn);
4420         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4421         smbd_unlock_socket(req->xconn);
4422
4423  out:
4424         END_PROFILE(SMBreadX);
4425         return;
4426 }
4427
4428 /****************************************************************************
4429  Error replies to writebraw must have smb_wct == 1. Fix this up.
4430 ****************************************************************************/
4431
4432 void error_to_writebrawerr(struct smb_request *req)
4433 {
4434         uint8_t *old_outbuf = req->outbuf;
4435
4436         reply_outbuf(req, 1, 0);
4437
4438         memcpy(req->outbuf, old_outbuf, smb_size);
4439         TALLOC_FREE(old_outbuf);
4440 }
4441
4442 /****************************************************************************
4443  Read 4 bytes of a smb packet and return the smb length of the packet.
4444  Store the result in the buffer. This version of the function will
4445  never return a session keepalive (length of zero).
4446  Timeout is in milliseconds.
4447 ****************************************************************************/
4448
4449 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4450                                 size_t *len)
4451 {
4452         uint8_t msgtype = NBSSkeepalive;
4453
4454         while (msgtype == NBSSkeepalive) {
4455                 NTSTATUS status;
4456
4457                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4458                                                           len);
4459                 if (!NT_STATUS_IS_OK(status)) {
4460                         char addr[INET6_ADDRSTRLEN];
4461                         /* Try and give an error message
4462                          * saying what client failed. */
4463                         DEBUG(0, ("read_smb_length_return_keepalive failed for "
4464                                   "client %s read error = %s.\n",
4465                                   get_peer_addr(fd,addr,sizeof(addr)),
4466                                   nt_errstr(status)));
4467                         return status;
4468                 }
4469
4470                 msgtype = CVAL(inbuf, 0);
4471         }
4472
4473         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4474                   (unsigned long)len));
4475
4476         return NT_STATUS_OK;
4477 }
4478
4479 /****************************************************************************
4480  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4481 ****************************************************************************/
4482
4483 void reply_writebraw(struct smb_request *req)
4484 {
4485         connection_struct *conn = req->conn;
4486         struct smbXsrv_connection *xconn = req->xconn;
4487         char *buf = NULL;
4488         ssize_t nwritten=0;
4489         ssize_t total_written=0;
4490         size_t numtowrite=0;
4491         size_t tcount;
4492         off_t startpos;
4493         const char *data=NULL;
4494         bool write_through;
4495         files_struct *fsp;
4496         struct lock_struct lock;
4497         NTSTATUS status;
4498
4499         START_PROFILE(SMBwritebraw);
4500
4501         /*
4502          * If we ever reply with an error, it must have the SMB command
4503          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4504          * we're finished.
4505          */
4506         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4507
4508         if (srv_is_signing_active(xconn)) {
4509                 END_PROFILE(SMBwritebraw);
4510                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4511                                 "raw reads/writes are disallowed.");
4512         }
4513
4514         if (req->wct < 12) {
4515                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516                 error_to_writebrawerr(req);
4517                 END_PROFILE(SMBwritebraw);
4518                 return;
4519         }
4520
4521         if (xconn->smb1.echo_handler.trusted_fde) {
4522                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4523                          "'async smb echo handler = yes'\n"));
4524                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4525                 error_to_writebrawerr(req);
4526                 END_PROFILE(SMBwritebraw);
4527                 return;
4528         }
4529
4530         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4531         if (!check_fsp(conn, req, fsp)) {
4532                 error_to_writebrawerr(req);
4533                 END_PROFILE(SMBwritebraw);
4534                 return;
4535         }
4536
4537         if (!CHECK_WRITE(fsp)) {
4538                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4539                 error_to_writebrawerr(req);
4540                 END_PROFILE(SMBwritebraw);
4541                 return;
4542         }
4543
4544         tcount = IVAL(req->vwv+1, 0);
4545         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4546         write_through = BITSETW(req->vwv+7,0);
4547
4548         /* We have to deal with slightly different formats depending
4549                 on whether we are using the core+ or lanman1.0 protocol */
4550
4551         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4552                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4553                 data = smb_buf_const(req->inbuf);
4554         } else {
4555                 numtowrite = SVAL(req->vwv+10, 0);
4556                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4557         }
4558
4559         /* Ensure we don't write bytes past the end of this packet. */
4560         /*
4561          * This already protects us against CVE-2017-12163.
4562          */
4563         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4564                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4565                 error_to_writebrawerr(req);
4566                 END_PROFILE(SMBwritebraw);
4567                 return;
4568         }
4569
4570         if (!fsp->print_file) {
4571                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4572                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4573                     &lock);
4574
4575                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4576                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4577                         error_to_writebrawerr(req);
4578                         END_PROFILE(SMBwritebraw);
4579                         return;
4580                 }
4581         }
4582
4583         if (numtowrite>0) {
4584                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4585         }
4586
4587         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4588                         "wrote=%d sync=%d\n",
4589                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4590                 (int)nwritten, (int)write_through));
4591
4592         if (nwritten < (ssize_t)numtowrite)  {
4593                 reply_nterror(req, NT_STATUS_DISK_FULL);
4594                 error_to_writebrawerr(req);
4595                 goto out;
4596         }
4597
4598         total_written = nwritten;
4599
4600         /* Allocate a buffer of 64k + length. */
4601         buf = talloc_array(NULL, char, 65540);
4602         if (!buf) {
4603                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4604                 error_to_writebrawerr(req);
4605                 goto out;
4606         }
4607
4608         /* Return a SMBwritebraw message to the redirector to tell
4609          * it to send more bytes */
4610
4611         memcpy(buf, req->inbuf, smb_size);
4612         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4613         SCVAL(buf,smb_com,SMBwritebraw);
4614         SSVALS(buf,smb_vwv0,0xFFFF);
4615         show_msg(buf);
4616         if (!srv_send_smb(req->xconn,
4617                           buf,
4618                           false, 0, /* no signing */
4619                           IS_CONN_ENCRYPTED(conn),
4620                           &req->pcd)) {
4621                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4622                         "failed.");
4623         }
4624
4625         /* Now read the raw data into the buffer and write it */
4626         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4627                                  &numtowrite);
4628         if (!NT_STATUS_IS_OK(status)) {
4629                 exit_server_cleanly("secondary writebraw failed");
4630         }
4631
4632         /* Set up outbuf to return the correct size */
4633         reply_outbuf(req, 1, 0);
4634
4635         if (numtowrite != 0) {
4636
4637                 if (numtowrite > 0xFFFF) {
4638                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4639                                 "raw requested (%u). Terminating\n",
4640                                 (unsigned int)numtowrite ));
4641                         exit_server_cleanly("secondary writebraw failed");
4642                 }
4643
4644                 if (tcount > nwritten+numtowrite) {
4645                         DEBUG(3,("reply_writebraw: Client overestimated the "
4646                                 "write %d %d %d\n",
4647                                 (int)tcount,(int)nwritten,(int)numtowrite));
4648                 }
4649
4650                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4651                                             numtowrite);
4652
4653                 if (!NT_STATUS_IS_OK(status)) {
4654                         /* Try and give an error message
4655                          * saying what client failed. */
4656                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4657                                   "raw read failed (%s) for client %s. "
4658                                   "Terminating\n", nt_errstr(status),
4659                                   smbXsrv_connection_dbg(xconn)));
4660                         exit_server_cleanly("secondary writebraw failed");
4661                 }
4662
4663                 /*
4664                  * We are not vulnerable to CVE-2017-12163
4665                  * here as we are guaranteed to have numtowrite
4666                  * bytes available - we just read from the client.
4667                  */
4668                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4669                 if (nwritten == -1) {
4670                         TALLOC_FREE(buf);
4671                         reply_nterror(req, map_nt_error_from_unix(errno));
4672                         error_to_writebrawerr(req);
4673                         goto out;
4674                 }
4675
4676                 if (nwritten < (ssize_t)numtowrite) {
4677                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4678                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4679                 }
4680
4681                 if (nwritten > 0) {
4682                         total_written += nwritten;
4683                 }
4684         }
4685
4686         TALLOC_FREE(buf);
4687         SSVAL(req->outbuf,smb_vwv0,total_written);
4688
4689         status = sync_file(conn, fsp, write_through);
4690         if (!NT_STATUS_IS_OK(status)) {
4691                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4692                          fsp_str_dbg(fsp), nt_errstr(status)));
4693                 reply_nterror(req, status);
4694                 error_to_writebrawerr(req);
4695                 goto out;
4696         }
4697
4698         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4699                 "wrote=%d\n",
4700                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4701                 (int)total_written));
4702
4703         /* We won't return a status if write through is not selected - this
4704          * follows what WfWg does */
4705         END_PROFILE(SMBwritebraw);
4706
4707         if (!write_through && total_written==tcount) {
4708
4709 #if RABBIT_PELLET_FIX
4710                 /*
4711                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4712                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4713                  * JRA.
4714                  */
4715                 if (!send_keepalive(xconn->transport.sock)) {
4716                         exit_server_cleanly("reply_writebraw: send of "
4717                                 "keepalive failed");
4718                 }
4719 #endif
4720                 TALLOC_FREE(req->outbuf);
4721         }
4722         return;
4723
4724 out:
4725         END_PROFILE(SMBwritebraw);
4726         return;
4727 }
4728
4729 #undef DBGC_CLASS
4730 #define DBGC_CLASS DBGC_LOCKING
4731
4732 /****************************************************************************
4733  Reply to a writeunlock (core+).
4734 ****************************************************************************/
4735
4736 void reply_writeunlock(struct smb_request *req)
4737 {
4738         connection_struct *conn = req->conn;
4739         ssize_t nwritten = -1;
4740         size_t numtowrite;
4741         size_t remaining;
4742         off_t startpos;
4743         const char *data;
4744         NTSTATUS status = NT_STATUS_OK;
4745         files_struct *fsp;
4746         struct lock_struct lock;
4747         int saved_errno = 0;
4748
4749         START_PROFILE(SMBwriteunlock);
4750
4751         if (req->wct < 5) {
4752                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4753                 END_PROFILE(SMBwriteunlock);
4754                 return;
4755         }
4756
4757         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4758
4759         if (!check_fsp(conn, req, fsp)) {
4760                 END_PROFILE(SMBwriteunlock);
4761                 return;
4762         }
4763
4764         if (!CHECK_WRITE(fsp)) {
4765                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4766                 END_PROFILE(SMBwriteunlock);
4767                 return;
4768         }
4769
4770         numtowrite = SVAL(req->vwv+1, 0);
4771         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4772         data = (const char *)req->buf + 3;
4773
4774         /*
4775          * Ensure client isn't asking us to write more than
4776          * they sent. CVE-2017-12163.
4777          */
4778         remaining = smbreq_bufrem(req, data);
4779         if (numtowrite > remaining) {
4780                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4781                 END_PROFILE(SMBwriteunlock);
4782                 return;
4783         }
4784
4785         if (!fsp->print_file && numtowrite > 0) {
4786                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4787                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4788                     &lock);
4789
4790                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4791                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4792                         END_PROFILE(SMBwriteunlock);
4793                         return;
4794                 }
4795         }
4796
4797         /* The special X/Open SMB protocol handling of
4798            zero length writes is *NOT* done for
4799            this call */
4800         if(numtowrite == 0) {
4801                 nwritten = 0;
4802         } else {
4803                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4804                 saved_errno = errno;
4805         }
4806
4807         status = sync_file(conn, fsp, False /* write through */);
4808         if (!NT_STATUS_IS_OK(status)) {
4809                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4810                          fsp_str_dbg(fsp), nt_errstr(status)));
4811                 reply_nterror(req, status);
4812                 goto out;
4813         }
4814
4815         if(nwritten < 0) {
4816                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4817                 goto out;
4818         }
4819
4820         if((nwritten < numtowrite) && (numtowrite != 0)) {
4821                 reply_nterror(req, NT_STATUS_DISK_FULL);
4822                 goto out;
4823         }
4824
4825         if (numtowrite && !fsp->print_file) {
4826                 struct smbd_lock_element l = {
4827                         .smblctx = req->smbpid,
4828                         .brltype = UNLOCK_LOCK,
4829                         .offset = startpos,
4830                         .count = numtowrite,
4831                 };
4832                 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
4833                 if (NT_STATUS_V(status)) {
4834                         reply_nterror(req, status);
4835                         goto out;
4836                 }
4837         }
4838
4839         reply_outbuf(req, 1, 0);
4840
4841         SSVAL(req->outbuf,smb_vwv0,nwritten);
4842
4843         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4844                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4845
4846 out:
4847         END_PROFILE(SMBwriteunlock);
4848         return;
4849 }
4850
4851 #undef DBGC_CLASS
4852 #define DBGC_CLASS DBGC_ALL
4853
4854 /****************************************************************************
4855  Reply to a write.
4856 ****************************************************************************/
4857
4858 void reply_write(struct smb_request *req)
4859 {
4860         connection_struct *conn = req->conn;
4861         size_t numtowrite;
4862         size_t remaining;
4863         ssize_t nwritten = -1;
4864         off_t startpos;
4865         const char *data;
4866         files_struct *fsp;
4867         struct lock_struct lock;
4868         NTSTATUS status;
4869         int saved_errno = 0;
4870
4871         START_PROFILE(SMBwrite);
4872
4873         if (req->wct < 5) {
4874                 END_PROFILE(SMBwrite);
4875                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4876                 return;
4877         }
4878
4879         /* If it's an IPC, pass off the pipe handler. */
4880         if (IS_IPC(conn)) {
4881                 reply_pipe_write(req);
4882                 END_PROFILE(SMBwrite);
4883                 return;
4884         }
4885
4886         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4887
4888         if (!check_fsp(conn, req, fsp)) {
4889                 END_PROFILE(SMBwrite);
4890                 return;
4891         }
4892
4893         if (!CHECK_WRITE(fsp)) {
4894                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4895                 END_PROFILE(SMBwrite);
4896                 return;
4897         }
4898
4899         numtowrite = SVAL(req->vwv+1, 0);
4900         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4901         data = (const char *)req->buf + 3;
4902
4903         /*
4904          * Ensure client isn't asking us to write more than
4905          * they sent. CVE-2017-12163.
4906          */
4907         remaining = smbreq_bufrem(req, data);
4908         if (numtowrite > remaining) {
4909                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4910                 END_PROFILE(SMBwrite);
4911                 return;
4912         }
4913
4914         if (!fsp->print_file) {
4915                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4916                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4917                         &lock);
4918
4919                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4920                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4921                         END_PROFILE(SMBwrite);
4922                         return;
4923                 }
4924         }
4925
4926         /*
4927          * X/Open SMB protocol says that if smb_vwv1 is
4928          * zero then the file size should be extended or
4929          * truncated to the size given in smb_vwv[2-3].
4930          */
4931
4932         if(numtowrite == 0) {
4933                 /*
4934                  * This is actually an allocate call, and set EOF. JRA.
4935                  */
4936                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4937                 if (nwritten < 0) {
4938                         reply_nterror(req, NT_STATUS_DISK_FULL);
4939                         goto out;
4940                 }
4941                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4942                 if (nwritten < 0) {
4943                         reply_nterror(req, NT_STATUS_DISK_FULL);
4944                         goto out;
4945                 }
4946                 trigger_write_time_update_immediate(fsp);
4947         } else {
4948                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4949         }
4950
4951         status = sync_file(conn, fsp, False);
4952         if (!NT_STATUS_IS_OK(status)) {
4953                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4954                          fsp_str_dbg(fsp), nt_errstr(status)));
4955                 reply_nterror(req, status);
4956                 goto out;
4957         }
4958
4959         if(nwritten < 0) {
4960                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4961                 goto out;
4962         }
4963
4964         if((nwritten == 0) && (numtowrite != 0)) {
4965                 reply_nterror(req, NT_STATUS_DISK_FULL);
4966                 goto out;
4967         }
4968
4969         reply_outbuf(req, 1, 0);
4970
4971         SSVAL(req->outbuf,smb_vwv0,nwritten);
4972
4973         if (nwritten < (ssize_t)numtowrite) {
4974                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4975                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4976         }
4977
4978         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4979
4980 out:
4981         END_PROFILE(SMBwrite);
4982         return;
4983 }
4984
4985 /****************************************************************************
4986  Ensure a buffer is a valid writeX for recvfile purposes.
4987 ****************************************************************************/
4988
4989 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4990                                                 (2*14) + /* word count (including bcc) */ \
4991                                                 1 /* pad byte */)
4992
4993 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4994                             const uint8_t *inbuf)
4995 {
4996         size_t numtowrite;
4997         unsigned int doff = 0;
4998         size_t len = smb_len_large(inbuf);
4999         uint16_t fnum;
5000         struct smbXsrv_open *op = NULL;
5001         struct files_struct *fsp = NULL;
5002         NTSTATUS status;
5003
5004         if (is_encrypted_packet(inbuf)) {
5005                 /* Can't do this on encrypted
5006                  * connections. */
5007                 return false;
5008         }
5009
5010         if (CVAL(inbuf,smb_com) != SMBwriteX) {
5011                 return false;
5012         }
5013
5014         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5015                         CVAL(inbuf,smb_wct) != 14) {
5016                 DEBUG(10,("is_valid_writeX_buffer: chained or "
5017                         "invalid word length.\n"));
5018                 return false;
5019         }
5020
5021         fnum = SVAL(inbuf, smb_vwv2);
5022         status = smb1srv_open_lookup(xconn,
5023                                      fnum,
5024                                      0, /* now */
5025                                      &op);
5026         if (!NT_STATUS_IS_OK(status)) {
5027                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5028                 return false;
5029         }
5030         fsp = op->compat;
5031         if (fsp == NULL) {
5032                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5033                 return false;
5034         }
5035         if (fsp->conn == NULL) {
5036                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5037                 return false;
5038         }
5039
5040         if (IS_IPC(fsp->conn)) {
5041                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5042                 return false;
5043         }
5044         if (IS_PRINT(fsp->conn)) {
5045                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5046                 return false;
5047         }
5048         if (fsp->base_fsp != NULL) {
5049                 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5050                 return false;
5051         }
5052         doff = SVAL(inbuf,smb_vwv11);
5053
5054         numtowrite = SVAL(inbuf,smb_vwv10);
5055
5056         if (len > doff && len - doff > 0xFFFF) {
5057                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5058         }
5059
5060         if (numtowrite == 0) {
5061                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5062                 return false;
5063         }
5064
5065         /* Ensure the sizes match up. */
5066         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5067                 /* no pad byte...old smbclient :-( */
5068                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5069                         (unsigned int)doff,
5070                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5071                 return false;
5072         }
5073
5074         if (len - doff != numtowrite) {
5075                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5076                         "len = %u, doff = %u, numtowrite = %u\n",
5077                         (unsigned int)len,
5078                         (unsigned int)doff,
5079                         (unsigned int)numtowrite ));
5080                 return false;
5081         }
5082
5083         DEBUG(10,("is_valid_writeX_buffer: true "
5084                 "len = %u, doff = %u, numtowrite = %u\n",
5085                 (unsigned int)len,
5086                 (unsigned int)doff,
5087                 (unsigned int)numtowrite ));
5088
5089         return true;
5090 }
5091
5092 /****************************************************************************
5093  Reply to a write and X.
5094 ****************************************************************************/
5095
5096 void reply_write_and_X(struct smb_request *req)
5097 {
5098         connection_struct *conn = req->conn;
5099         struct smbXsrv_connection *xconn = req->xconn;
5100         files_struct *fsp;
5101         struct lock_struct lock;
5102         off_t startpos;
5103         size_t numtowrite;
5104         bool write_through;
5105         ssize_t nwritten;
5106         unsigned int smb_doff;
5107         unsigned int smblen;
5108         const char *data;
5109         NTSTATUS status;
5110         int saved_errno = 0;
5111
5112         START_PROFILE(SMBwriteX);
5113
5114         if ((req->wct != 12) && (req->wct != 14)) {
5115                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116                 goto out;
5117         }
5118
5119         numtowrite = SVAL(req->vwv+10, 0);
5120         smb_doff = SVAL(req->vwv+11, 0);
5121         smblen = smb_len(req->inbuf);
5122
5123         if (req->unread_bytes > 0xFFFF ||
5124                         (smblen > smb_doff &&
5125                                 smblen - smb_doff > 0xFFFF)) {
5126                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5127         }
5128
5129         if (req->unread_bytes) {
5130                 /* Can't do a recvfile write on IPC$ */
5131                 if (IS_IPC(conn)) {
5132                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133                         goto out;
5134                 }
5135                 if (numtowrite != req->unread_bytes) {
5136                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5137                         goto out;
5138                 }
5139         } else {
5140                 /*
5141                  * This already protects us against CVE-2017-12163.
5142                  */
5143                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5144                                 smb_doff + numtowrite > smblen) {
5145                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146                         goto out;
5147                 }
5148         }
5149
5150         /* If it's an IPC, pass off the pipe handler. */
5151         if (IS_IPC(conn)) {
5152                 if (req->unread_bytes) {
5153                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5154                         goto out;
5155                 }
5156                 reply_pipe_write_and_X(req);
5157                 goto out;
5158         }
5159
5160         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5161         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5162         write_through = BITSETW(req->vwv+7,0);
5163
5164         if (!check_fsp(conn, req, fsp)) {
5165                 goto out;
5166         }
5167
5168         if (!CHECK_WRITE(fsp)) {
5169                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5170                 goto out;
5171         }
5172
5173         data = smb_base(req->inbuf) + smb_doff;
5174
5175         if(req->wct == 14) {
5176                 /*
5177                  * This is a large offset (64 bit) write.
5178                  */
5179                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5180
5181         }
5182
5183         /* X/Open SMB protocol says that, unlike SMBwrite
5184         if the length is zero then NO truncation is
5185         done, just a write of zero. To truncate a file,
5186         use SMBwrite. */
5187
5188         if(numtowrite == 0) {
5189                 nwritten = 0;
5190         } else {
5191                 if (req->unread_bytes == 0) {
5192                         status = schedule_aio_write_and_X(conn,
5193                                                 req,
5194                                                 fsp,
5195                                                 data,
5196                                                 startpos,
5197                                                 numtowrite);
5198
5199                         if (NT_STATUS_IS_OK(status)) {
5200                                 /* write scheduled - we're done. */
5201                                 goto out;
5202                         }
5203                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5204                                 /* Real error - report to client. */
5205                                 reply_nterror(req, status);
5206                                 goto out;
5207                         }
5208                         /* NT_STATUS_RETRY - fall through to sync write. */
5209                 }
5210
5211                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5212                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5213                     &lock);
5214
5215                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5216                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5217                         goto out;
5218                 }
5219
5220                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5221                 saved_errno = errno;
5222         }
5223
5224         if(nwritten < 0) {
5225                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5226                 goto out;
5227         }
5228
5229         if((nwritten == 0) && (numtowrite != 0)) {
5230                 reply_nterror(req, NT_STATUS_DISK_FULL);
5231                 goto out;
5232         }
5233
5234         reply_outbuf(req, 6, 0);
5235         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5236         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
5237         SSVAL(req->outbuf,smb_vwv2,nwritten);
5238         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5239
5240         DEBUG(3,("writeX %s num=%d wrote=%d\n",
5241                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5242
5243         status = sync_file(conn, fsp, write_through);
5244         if (!NT_STATUS_IS_OK(status)) {
5245                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5246                          fsp_str_dbg(fsp), nt_errstr(status)));
5247                 reply_nterror(req, status);
5248                 goto out;
5249         }
5250
5251         END_PROFILE(SMBwriteX);
5252         return;
5253
5254 out:
5255         if (req->unread_bytes) {
5256                 /* writeX failed. drain socket. */
5257                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5258                                 req->unread_bytes) {
5259                         smb_panic("failed to drain pending bytes");
5260                 }
5261                 req->unread_bytes = 0;
5262         }
5263
5264         END_PROFILE(SMBwriteX);
5265         return;
5266 }
5267
5268 /****************************************************************************
5269  Reply to a lseek.
5270 ****************************************************************************/
5271
5272 void reply_lseek(struct smb_request *req)
5273 {
5274         connection_struct *conn = req->conn;
5275         off_t startpos;
5276         off_t res= -1;
5277         int mode,umode;
5278         files_struct *fsp;
5279
5280         START_PROFILE(SMBlseek);
5281
5282         if (req->wct < 4) {
5283                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284                 END_PROFILE(SMBlseek);
5285                 return;
5286         }
5287
5288         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5289
5290         if (!check_fsp(conn, req, fsp)) {
5291                 return;
5292         }
5293
5294         flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5295
5296         mode = SVAL(req->vwv+1, 0) & 3;
5297         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5298         startpos = (off_t)IVALS(req->vwv+2, 0);
5299
5300         switch (mode) {
5301                 case 0:
5302                         umode = SEEK_SET;
5303                         res = startpos;
5304                         break;
5305                 case 1:
5306                         umode = SEEK_CUR;
5307                         res = fsp->fh->pos + startpos;
5308                         break;
5309                 case 2:
5310                         umode = SEEK_END;
5311                         break;
5312                 default:
5313                         umode = SEEK_SET;
5314                         res = startpos;
5315                         break;
5316         }
5317
5318         if (umode == SEEK_END) {
5319                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5320                         if(errno == EINVAL) {
5321                                 off_t current_pos = startpos;
5322
5323                                 if(fsp_stat(fsp) == -1) {
5324                                         reply_nterror(req,
5325                                                 map_nt_error_from_unix(errno));
5326                                         END_PROFILE(SMBlseek);
5327                                         return;
5328                                 }
5329
5330                                 current_pos += fsp->fsp_name->st.st_ex_size;
5331                                 if(current_pos < 0)
5332                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5333                         }
5334                 }
5335
5336                 if(res == -1) {
5337                         reply_nterror(req, map_nt_error_from_unix(errno));
5338                         END_PROFILE(SMBlseek);
5339                         return;
5340                 }
5341         }
5342
5343         fsp->fh->pos = res;
5344
5345         reply_outbuf(req, 2, 0);
5346         SIVAL(req->outbuf,smb_vwv0,res);
5347
5348         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5349                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5350
5351         END_PROFILE(SMBlseek);
5352         return;
5353 }
5354
5355 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5356                                              void *private_data)
5357 {
5358         connection_struct *conn = talloc_get_type_abort(
5359                 private_data, connection_struct);
5360
5361         if (conn != fsp->conn) {
5362                 return NULL;
5363         }
5364         if (fsp->fh->fd == -1) {
5365                 return NULL;
5366         }
5367         sync_file(conn, fsp, True /* write through */);
5368
5369         return NULL;
5370 }
5371
5372 /****************************************************************************
5373  Reply to a flush.
5374 ****************************************************************************/
5375
5376 void reply_flush(struct smb_request *req)
5377 {
5378         connection_struct *conn = req->conn;
5379         uint16_t fnum;
5380         files_struct *fsp;
5381
5382         START_PROFILE(SMBflush);
5383
5384         if (req->wct < 1) {
5385                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5386                 return;
5387         }
5388
5389         fnum = SVAL(req->vwv+0, 0);
5390         fsp = file_fsp(req, fnum);
5391
5392         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5393                 return;
5394         }
5395
5396         if (!fsp) {
5397                 files_forall(req->sconn, file_sync_one_fn, conn);
5398         } else {
5399                 NTSTATUS status = sync_file(conn, fsp, True);
5400                 if (!NT_STATUS_IS_OK(status)) {
5401                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5402                                 fsp_str_dbg(fsp), nt_errstr(status)));
5403                         reply_nterror(req, status);
5404                         END_PROFILE(SMBflush);
5405                         return;
5406                 }
5407         }
5408
5409         reply_outbuf(req, 0, 0);
5410
5411         DEBUG(3,("flush\n"));
5412         END_PROFILE(SMBflush);
5413         return;
5414 }
5415
5416 /****************************************************************************
5417  Reply to a exit.
5418  conn POINTER CAN BE NULL HERE !
5419 ****************************************************************************/
5420
5421 void reply_exit(struct smb_request *req)
5422 {
5423         START_PROFILE(SMBexit);
5424
5425         file_close_pid(req->sconn, req->smbpid, req->vuid);
5426
5427         reply_outbuf(req, 0, 0);
5428
5429         DEBUG(3,("exit\n"));
5430
5431         END_PROFILE(SMBexit);
5432         return;
5433 }
5434
5435 struct reply_close_state {
5436         files_struct *fsp;
5437         struct smb_request *smbreq;
5438 };
5439
5440 static void do_smb1_close(struct tevent_req *req);
5441
5442 void reply_close(struct smb_request *req)
5443 {
5444         connection_struct *conn = req->conn;
5445         NTSTATUS status = NT_STATUS_OK;
5446         files_struct *fsp = NULL;
5447         START_PROFILE(SMBclose);
5448
5449         if (req->wct < 3) {
5450                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5451                 END_PROFILE(SMBclose);
5452                 return;
5453         }
5454
5455         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5456
5457         /*
5458          * We can only use check_fsp if we know it's not a directory.
5459          */
5460
5461         if (!check_fsp_open(conn, req, fsp)) {
5462                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5463                 END_PROFILE(SMBclose);
5464                 return;
5465         }
5466
5467         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5468                   fsp->is_directory ? "directory" : "file",
5469                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5470                   conn->num_files_open));
5471
5472         if (!fsp->is_directory) {
5473                 time_t t;
5474
5475                 /*
5476                  * Take care of any time sent in the close.
5477                  */
5478
5479                 t = srv_make_unix_date3(req->vwv+1);
5480                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5481         }
5482
5483         if (fsp->num_aio_requests != 0) {
5484
5485                 struct reply_close_state *state;
5486
5487                 DEBUG(10, ("closing with aio %u requests pending\n",
5488                            fsp->num_aio_requests));
5489
5490                 /*
5491                  * We depend on the aio_extra destructor to take care of this
5492                  * close request once fsp->num_aio_request drops to 0.
5493                  */
5494
5495                 fsp->deferred_close = tevent_wait_send(
5496                         fsp, fsp->conn->sconn->ev_ctx);
5497                 if (fsp->deferred_close == NULL) {
5498                         status = NT_STATUS_NO_MEMORY;
5499                         goto done;
5500                 }
5501
5502                 state = talloc(fsp, struct reply_close_state);
5503                 if (state == NULL) {
5504                         TALLOC_FREE(fsp->deferred_close);
5505                         status = NT_STATUS_NO_MEMORY;
5506                         goto done;
5507                 }
5508                 state->fsp = fsp;
5509                 state->smbreq = talloc_move(fsp, &req);
5510                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5511                                         state);
5512                 END_PROFILE(SMBclose);
5513                 return;
5514         }
5515
5516         /*
5517          * close_file() returns the unix errno if an error was detected on
5518          * close - normally this is due to a disk full error. If not then it
5519          * was probably an I/O error.
5520          */
5521
5522         status = close_file(req, fsp, NORMAL_CLOSE);
5523 done:
5524         if (!NT_STATUS_IS_OK(status)) {
5525                 reply_nterror(req, status);
5526                 END_PROFILE(SMBclose);
5527                 return;
5528         }
5529
5530         reply_outbuf(req, 0, 0);
5531         END_PROFILE(SMBclose);
5532         return;
5533 }
5534
5535 static void do_smb1_close(struct tevent_req *req)
5536 {
5537         struct reply_close_state *state = tevent_req_callback_data(
5538                 req, struct reply_close_state);
5539         struct smb_request *smbreq;
5540         NTSTATUS status;
5541         int ret;
5542
5543         ret = tevent_wait_recv(req);
5544         TALLOC_FREE(req);
5545         if (ret != 0) {
5546                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5547                            strerror(ret)));
5548                 /*
5549                  * Continue anyway, this should never happen
5550                  */
5551         }
5552
5553         /*
5554          * fsp->smb2_close_request right now is a talloc grandchild of
5555          * fsp. When we close_file(fsp), it would go with it. No chance to
5556          * reply...
5557          */
5558         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5559
5560         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5561         if (NT_STATUS_IS_OK(status)) {
5562                 reply_outbuf(smbreq, 0, 0);
5563         } else {
5564                 reply_nterror(smbreq, status);
5565         }
5566         if (!srv_send_smb(smbreq->xconn,
5567                         (char *)smbreq->outbuf,
5568                         true,
5569                         smbreq->seqnum+1,
5570                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5571                         NULL)) {
5572                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5573                                     "failed.");
5574         }
5575         TALLOC_FREE(smbreq);
5576 }
5577
5578 /****************************************************************************
5579  Reply to a writeclose (Core+ protocol).
5580 ****************************************************************************/
5581
5582 void reply_writeclose(struct smb_request *req)
5583 {
5584         connection_struct *conn = req->conn;
5585         size_t numtowrite;
5586         size_t remaining;
5587         ssize_t nwritten = -1;
5588         NTSTATUS close_status = NT_STATUS_OK;
5589         off_t startpos;
5590         const char *data;
5591         struct timespec mtime;
5592         files_struct *fsp;
5593         struct lock_struct lock;
5594
5595         START_PROFILE(SMBwriteclose);
5596
5597         if (req->wct < 6) {
5598                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5599                 END_PROFILE(SMBwriteclose);
5600                 return;
5601         }
5602
5603         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5604
5605         if (!check_fsp(conn, req, fsp)) {
5606                 END_PROFILE(SMBwriteclose);
5607                 return;
5608         }
5609         if (!CHECK_WRITE(fsp)) {
5610                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5611                 END_PROFILE(SMBwriteclose);
5612                 return;
5613         }
5614
5615         numtowrite = SVAL(req->vwv+1, 0);
5616         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5617         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5618         data = (const char *)req->buf + 1;
5619
5620         /*
5621          * Ensure client isn't asking us to write more than
5622          * they sent. CVE-2017-12163.
5623          */
5624         remaining = smbreq_bufrem(req, data);
5625         if (numtowrite > remaining) {
5626                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5627                 END_PROFILE(SMBwriteclose);
5628                 return;
5629         }
5630
5631         if (fsp->print_file == NULL) {
5632                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5633                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5634                     &lock);
5635
5636                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5637                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5638                         END_PROFILE(SMBwriteclose);
5639                         return;
5640                 }
5641         }
5642
5643         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5644
5645         set_close_write_time(fsp, mtime);
5646
5647         /*
5648          * More insanity. W2K only closes the file if writelen > 0.
5649          * JRA.
5650          */
5651
5652         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5653                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5654                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5655
5656         if (numtowrite) {
5657                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5658                          "file %s\n", fsp_str_dbg(fsp)));
5659                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5660                 fsp = NULL;
5661         }
5662
5663         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5664                 reply_nterror(req, NT_STATUS_DISK_FULL);
5665                 goto out;
5666         }
5667
5668         if(!NT_STATUS_IS_OK(close_status)) {
5669                 reply_nterror(req, close_status);
5670                 goto out;
5671         }
5672
5673         reply_outbuf(req, 1, 0);
5674
5675         SSVAL(req->outbuf,smb_vwv0,nwritten);
5676
5677 out:
5678
5679         END_PROFILE(SMBwriteclose);
5680         return;
5681 }
5682
5683 #undef DBGC_CLASS
5684 #define DBGC_CLASS DBGC_LOCKING
5685
5686 /****************************************************************************
5687  Reply to a lock.
5688 ****************************************************************************/
5689
5690 static void reply_lock_done(struct tevent_req *subreq);
5691
5692 void reply_lock(struct smb_request *req)
5693 {
5694         struct tevent_req *subreq = NULL;
5695         connection_struct *conn = req->conn;
5696         files_struct *fsp;
5697         struct smbd_lock_element *lck = NULL;
5698
5699         START_PROFILE(SMBlock);
5700
5701         if (req->wct < 5) {
5702                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5703                 END_PROFILE(SMBlock);
5704                 return;
5705         }
5706
5707         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5708
5709         if (!check_fsp(conn, req, fsp)) {
5710                 END_PROFILE(SMBlock);
5711                 return;
5712         }
5713
5714         lck = talloc(req, struct smbd_lock_element);
5715         if (lck == NULL) {
5716                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5717                 END_PROFILE(SMBlock);
5718                 return;
5719         }
5720
5721         *lck = (struct smbd_lock_element) {
5722                 .smblctx = req->smbpid,
5723                 .brltype = WRITE_LOCK,
5724                 .count = IVAL(req->vwv+1, 0),
5725                 .offset = IVAL(req->vwv+3, 0),
5726         };
5727
5728         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5729                    fsp->fh->fd,
5730                    fsp_fnum_dbg(fsp),
5731                    lck->offset,
5732                    lck->count);
5733
5734         subreq = smbd_smb1_do_locks_send(
5735                 fsp,
5736                 req->sconn->ev_ctx,
5737                 &req,
5738                 fsp,
5739                 0,
5740                 false,          /* large_offset */
5741                 WINDOWS_LOCK,
5742                 1,
5743                 lck);
5744         if (subreq == NULL) {
5745                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5746                 END_PROFILE(SMBlock);
5747                 return;
5748         }
5749         tevent_req_set_callback(subreq, reply_lock_done, NULL);
5750         END_PROFILE(SMBlock);
5751 }
5752
5753 static void reply_lock_done(struct tevent_req *subreq)
5754 {
5755         struct smb_request *req = NULL;
5756         NTSTATUS status;
5757         bool ok;
5758
5759         START_PROFILE(SMBlock);
5760
5761         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5762         SMB_ASSERT(ok);
5763
5764         status = smbd_smb1_do_locks_recv(subreq);
5765         TALLOC_FREE(subreq);
5766
5767         if (NT_STATUS_IS_OK(status)) {
5768                 reply_outbuf(req, 0, 0);
5769         } else {
5770                 reply_nterror(req, status);
5771         }
5772
5773         ok = srv_send_smb(req->xconn,
5774                           (char *)req->outbuf,
5775                           true,
5776                           req->seqnum+1,
5777                           IS_CONN_ENCRYPTED(req->conn),
5778                           NULL);
5779         if (!ok) {
5780                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5781         }
5782         TALLOC_FREE(req);
5783         END_PROFILE(SMBlock);
5784 }
5785
5786 /****************************************************************************
5787  Reply to a unlock.
5788 ****************************************************************************/
5789
5790 void reply_unlock(struct smb_request *req)
5791 {
5792         connection_struct *conn = req->conn;
5793         NTSTATUS status;
5794         files_struct *fsp;
5795         struct smbd_lock_element lck;
5796
5797         START_PROFILE(SMBunlock);
5798
5799         if (req->wct < 5) {
5800                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5801                 END_PROFILE(SMBunlock);
5802                 return;
5803         }
5804
5805         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5806
5807         if (!check_fsp(conn, req, fsp)) {
5808                 END_PROFILE(SMBunlock);
5809                 return;
5810         }
5811
5812         lck = (struct smbd_lock_element) {
5813                 .smblctx = req->smbpid,
5814                 .brltype = UNLOCK_LOCK,
5815                 .offset = IVAL(req->vwv+3, 0),
5816                 .count = IVAL(req->vwv+1, 0),
5817         };
5818
5819         status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
5820
5821         if (!NT_STATUS_IS_OK(status)) {
5822                 reply_nterror(req, status);
5823                 END_PROFILE(SMBunlock);
5824                 return;
5825         }
5826
5827         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5828                    fsp->fh->fd,
5829                    fsp_fnum_dbg(fsp),
5830                    lck.offset,
5831                    lck.count);
5832
5833         reply_outbuf(req, 0, 0);
5834
5835         END_PROFILE(SMBunlock);
5836         return;
5837 }
5838
5839 #undef DBGC_CLASS
5840 #define DBGC_CLASS DBGC_ALL
5841
5842 /****************************************************************************
5843  Reply to a tdis.
5844  conn POINTER CAN BE NULL HERE !
5845 ****************************************************************************/
5846
5847 void reply_tdis(struct smb_request *req)
5848 {
5849         NTSTATUS status;
5850         connection_struct *conn = req->conn;
5851         struct smbXsrv_tcon *tcon;
5852
5853         START_PROFILE(SMBtdis);
5854
5855         if (!conn) {
5856                 DEBUG(4,("Invalid connection in tdis\n"));
5857                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5858                 END_PROFILE(SMBtdis);
5859                 return;
5860         }
5861
5862         tcon = conn->tcon;
5863         req->conn = NULL;
5864
5865         /*
5866          * TODO: cancel all outstanding requests on the tcon
5867          */
5868         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5869         if (!NT_STATUS_IS_OK(status)) {
5870                 DEBUG(0, ("reply_tdis: "
5871                           "smbXsrv_tcon_disconnect() failed: %s\n",
5872                           nt_errstr(status)));
5873                 /*
5874                  * If we hit this case, there is something completely
5875                  * wrong, so we better disconnect the transport connection.
5876                  */
5877                 END_PROFILE(SMBtdis);
5878                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5879                 return;
5880         }
5881
5882         TALLOC_FREE(tcon);
5883
5884         reply_outbuf(req, 0, 0);
5885         END_PROFILE(SMBtdis);
5886         return;
5887 }
5888
5889 /****************************************************************************
5890  Reply to a echo.
5891  conn POINTER CAN BE NULL HERE !
5892 ****************************************************************************/
5893
5894 void reply_echo(struct smb_request *req)
5895 {
5896         connection_struct *conn = req->conn;
5897         struct smb_perfcount_data local_pcd;
5898         struct smb_perfcount_data *cur_pcd;
5899         int smb_reverb;
5900         int seq_num;
5901
5902         START_PROFILE(SMBecho);
5903
5904         smb_init_perfcount_data(&local_pcd);
5905
5906         if (req->wct < 1) {
5907                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5908                 END_PROFILE(SMBecho);
5909                 return;
5910         }
5911
5912         smb_reverb = SVAL(req->vwv+0, 0);
5913
5914         reply_outbuf(req, 1, req->buflen);
5915
5916         /* copy any incoming data back out */
5917         if (req->buflen > 0) {
5918                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5919         }
5920
5921         if (smb_reverb > 100) {
5922                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5923                 smb_reverb = 100;
5924         }
5925
5926         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5927
5928                 /* this makes sure we catch the request pcd */
5929                 if (seq_num == smb_reverb) {
5930                         cur_pcd = &req->pcd;
5931                 } else {
5932                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5933                         cur_pcd = &local_pcd;
5934                 }
5935
5936                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5937
5938                 show_msg((char *)req->outbuf);
5939                 if (!srv_send_smb(req->xconn,
5940                                 (char *)req->outbuf,
5941                                 true, req->seqnum+1,
5942                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5943                                 cur_pcd))
5944                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5945         }
5946
5947         DEBUG(3,("echo %d times\n", smb_reverb));
5948
5949         TALLOC_FREE(req->outbuf);
5950
5951         END_PROFILE(SMBecho);
5952         return;
5953 }
5954
5955 /****************************************************************************
5956  Reply to a printopen.
5957 ****************************************************************************/
5958
5959 void reply_printopen(struct smb_request *req)
5960 {
5961         connection_struct *conn = req->conn;
5962         files_struct *fsp;
5963         NTSTATUS status;
5964
5965         START_PROFILE(SMBsplopen);
5966
5967         if (req->wct < 2) {
5968                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5969                 END_PROFILE(SMBsplopen);
5970                 return;
5971         }
5972
5973         if (!CAN_PRINT(conn)) {
5974                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5975                 END_PROFILE(SMBsplopen);
5976                 return;
5977         }
5978
5979         status = file_new(req, conn, &fsp);
5980         if(!NT_STATUS_IS_OK(status)) {
5981                 reply_nterror(req, status);
5982                 END_PROFILE(SMBsplopen);
5983                 return;
5984         }
5985
5986         /* Open for exclusive use, write only. */
5987         status = print_spool_open(fsp, NULL, req->vuid);
5988
5989         if (!NT_STATUS_IS_OK(status)) {
5990                 file_free(req, fsp);
5991                 reply_nterror(req, status);
5992                 END_PROFILE(SMBsplopen);
5993                 return;
5994         }
5995
5996         reply_outbuf(req, 1, 0);
5997         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5998
5999         DEBUG(3,("openprint fd=%d %s\n",
6000                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6001
6002         END_PROFILE(SMBsplopen);
6003         return;
6004 }
6005
6006 /****************************************************************************
6007  Reply to a printclose.
6008 ****************************************************************************/
6009
6010 void reply_printclose(struct smb_request *req)
6011 {
6012         connection_struct *conn = req->conn;
6013         files_struct *fsp;
6014         NTSTATUS status;
6015
6016         START_PROFILE(SMBsplclose);
6017
6018         if (req->wct < 1) {
6019                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6020                 END_PROFILE(SMBsplclose);
6021                 return;
6022         }
6023
6024         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6025
6026         if (!check_fsp(conn, req, fsp)) {
6027                 END_PROFILE(SMBsplclose);
6028                 return;
6029         }
6030
6031         if (!CAN_PRINT(conn)) {
6032                 reply_force_doserror(req, ERRSRV, ERRerror);
6033                 END_PROFILE(SMBsplclose);
6034                 return;
6035         }
6036
6037         DEBUG(3,("printclose fd=%d %s\n",
6038                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
6039
6040         status = close_file(req, fsp, NORMAL_CLOSE);
6041
6042         if(!NT_STATUS_IS_OK(status)) {
6043                 reply_nterror(req, status);
6044                 END_PROFILE(SMBsplclose);
6045                 return;
6046         }
6047
6048         reply_outbuf(req, 0, 0);
6049
6050         END_PROFILE(SMBsplclose);
6051         return;
6052 }
6053
6054 /****************************************************************************
6055  Reply to a printqueue.
6056 ****************************************************************************/
6057
6058 void reply_printqueue(struct smb_request *req)
6059 {
6060         connection_struct *conn = req->conn;
6061         int max_count;
6062         int start_index;
6063
6064         START_PROFILE(SMBsplretq);
6065
6066         if (req->wct < 2) {
6067                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6068                 END_PROFILE(SMBsplretq);
6069                 return;
6070         }
6071
6072         max_count = SVAL(req->vwv+0, 0);
6073         start_index = SVAL(req->vwv+1, 0);
6074
6075         /* we used to allow the client to get the cnum wrong, but that
6076            is really quite gross and only worked when there was only
6077            one printer - I think we should now only accept it if they
6078            get it right (tridge) */
6079         if (!CAN_PRINT(conn)) {
6080                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6081                 END_PROFILE(SMBsplretq);
6082                 return;
6083         }
6084
6085         reply_outbuf(req, 2, 3);
6086         SSVAL(req->outbuf,smb_vwv0,0);
6087         SSVAL(req->outbuf,smb_vwv1,0);
6088         SCVAL(smb_buf(req->outbuf),0,1);
6089         SSVAL(smb_buf(req->outbuf),1,0);
6090
6091         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6092                  start_index, max_count));
6093
6094         {
6095                 TALLOC_CTX *mem_ctx = talloc_tos();
6096                 NTSTATUS status;
6097                 WERROR werr;
6098                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
6099                 struct rpc_pipe_client *cli = NULL;
6100                 struct dcerpc_binding_handle *b = NULL;
6101                 struct policy_handle handle;
6102                 struct spoolss_DevmodeContainer devmode_ctr;
6103                 union spoolss_JobInfo *info;
6104                 uint32_t count;
6105                 uint32_t num_to_get;
6106                 uint32_t first;
6107                 uint32_t i;
6108
6109                 ZERO_STRUCT(handle);
6110
6111                 status = rpc_pipe_open_interface(mem_ctx,
6112                                                  &ndr_table_spoolss,
6113                                                  conn->session_info,
6114                                                  conn->sconn->remote_address,
6115                                                  conn->sconn->local_address,
6116                                                  conn->sconn->msg_ctx,
6117                                                  &cli);
6118                 if (!NT_STATUS_IS_OK(status)) {
6119                         DEBUG(0, ("reply_printqueue: "
6120                                   "could not connect to spoolss: %s\n",
6121                                   nt_errstr(status)));
6122                         reply_nterror(req, status);
6123                         goto out;
6124                 }
6125                 b = cli->binding_handle;
6126
6127                 ZERO_STRUCT(devmode_ctr);
6128
6129                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6130                                                 sharename,
6131                                                 NULL, devmode_ctr,
6132                                                 SEC_FLAG_MAXIMUM_ALLOWED,
6133                                                 &handle,
6134                                                 &werr);
6135                 if (!NT_STATUS_IS_OK(status)) {
6136                         reply_nterror(req, status);
6137                         goto out;
6138                 }
6139                 if (!W_ERROR_IS_OK(werr)) {
6140                         reply_nterror(req, werror_to_ntstatus(werr));
6141                         goto out;
6142                 }
6143
6144                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6145                                                &handle,
6146                                                0, /* firstjob */
6147                                                0xff, /* numjobs */
6148                                                2, /* level */
6149                                                0, /* offered */
6150                                                &count,
6151                                                &info);
6152                 if (!W_ERROR_IS_OK(werr)) {
6153                         reply_nterror(req, werror_to_ntstatus(werr));
6154                         goto out;
6155                 }
6156
6157                 if (max_count > 0) {
6158                         first = start_index;
6159                 } else {
6160                         first = start_index + max_count + 1;
6161                 }
6162
6163                 if (first >= count) {
6164                         num_to_get = first;
6165                 } else {
6166                         num_to_get = first + MIN(ABS(max_count), count - first);
6167                 }
6168
6169                 for (i = first; i < num_to_get; i++) {
6170                         char blob[28];
6171                         char *p = blob;
6172                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6173                         int qstatus;
6174                         size_t len = 0;
6175                         uint16_t qrapjobid = pjobid_to_rap(sharename,
6176                                                         info[i].info2.job_id);
6177
6178                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
6179                                 qstatus = 2;
6180                         } else {
6181                                 qstatus = 3;
6182                         }
6183
6184                         srv_put_dos_date2(p, 0, qtime);
6185                         SCVAL(p, 4, qstatus);
6186                         SSVAL(p, 5, qrapjobid);
6187                         SIVAL(p, 7, info[i].info2.size);
6188                         SCVAL(p, 11, 0);
6189                         status = srvstr_push(blob, req->flags2, p+12,
6190                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
6191                         if (!NT_STATUS_IS_OK(status)) {
6192                                 reply_nterror(req, status);
6193                                 goto out;
6194                         }
6195                         if (message_push_blob(
6196                                     &req->outbuf,
6197                                     data_blob_const(
6198                                             blob, sizeof(blob))) == -1) {
6199                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6200                                 goto out;
6201                         }
6202                 }
6203
6204                 if (count > 0) {
6205                         SSVAL(req->outbuf,smb_vwv0,count);
6206                         SSVAL(req->outbuf,smb_vwv1,
6207                               (max_count>0?first+count:first-1));
6208                         SCVAL(smb_buf(req->outbuf),0,1);
6209                         SSVAL(smb_buf(req->outbuf),1,28*count);
6210                 }
6211
6212
6213                 DEBUG(3, ("%u entries returned in queue\n",
6214                           (unsigned)count));
6215
6216 out:
6217                 if (b && is_valid_policy_hnd(&handle)) {
6218                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6219                 }
6220
6221         }
6222
6223         END_PROFILE(SMBsplretq);
6224         return;
6225 }
6226
6227 /****************************************************************************
6228  Reply to a printwrite.
6229 ****************************************************************************/
6230
6231 void reply_printwrite(struct smb_request *req)
6232 {
6233         connection_struct *conn = req->conn;
6234         int numtowrite;
6235         const char *data;
6236         files_struct *fsp;
6237
6238         START_PROFILE(SMBsplwr);
6239
6240         if (req->wct < 1) {
6241                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6242                 END_PROFILE(SMBsplwr);
6243                 return;
6244         }
6245
6246         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6247
6248         if (!check_fsp(conn, req, fsp)) {
6249                 END_PROFILE(SMBsplwr);
6250                 return;
6251         }
6252
6253         if (!fsp->print_file) {
6254                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6255                 END_PROFILE(SMBsplwr);
6256                 return;
6257         }
6258
6259         if (!CHECK_WRITE(fsp)) {
6260                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6261                 END_PROFILE(SMBsplwr);
6262                 return;
6263         }
6264
6265         numtowrite = SVAL(req->buf, 1);
6266
6267         /*
6268          * This already protects us against CVE-2017-12163.
6269          */
6270         if (req->buflen < numtowrite + 3) {
6271                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6272                 END_PROFILE(SMBsplwr);
6273                 return;
6274         }
6275
6276         data = (const char *)req->buf + 3;
6277
6278         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6279                 reply_nterror(req, map_nt_error_from_unix(errno));
6280                 END_PROFILE(SMBsplwr);
6281                 return;
6282         }
6283
6284         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6285
6286         END_PROFILE(SMBsplwr);
6287         return;
6288 }
6289
6290 /****************************************************************************
6291  Reply to a mkdir.
6292 ****************************************************************************/
6293
6294 void reply_mkdir(struct smb_request *req)
6295 {
6296         connection_struct *conn = req->conn;
6297         struct smb_filename *smb_dname = NULL;
6298         char *directory = NULL;
6299         NTSTATUS status;
6300         uint32_t ucf_flags;
6301         TALLOC_CTX *ctx = talloc_tos();
6302
6303         START_PROFILE(SMBmkdir);
6304
6305         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6306                             STR_TERMINATE, &status);
6307         if (!NT_STATUS_IS_OK(status)) {
6308                 reply_nterror(req, status);
6309                 goto out;
6310         }
6311
6312         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6313         status = filename_convert(ctx, conn,
6314                                  directory,
6315                                  ucf_flags,
6316                                  NULL,
6317                                  NULL,
6318                                  &smb_dname);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6321                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6322                                         ERRSRV, ERRbadpath);
6323                         goto out;
6324                 }
6325                 reply_nterror(req, status);
6326                 goto out;
6327         }
6328
6329         status = create_directory(conn, req, smb_dname);
6330
6331         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6332
6333         if (!NT_STATUS_IS_OK(status)) {
6334
6335                 if (!use_nt_status()
6336                     && NT_STATUS_EQUAL(status,
6337                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
6338                         /*
6339                          * Yes, in the DOS error code case we get a
6340                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6341                          * samba4 torture test.
6342                          */
6343                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6344                 }
6345
6346                 reply_nterror(req, status);
6347                 goto out;
6348         }
6349
6350         reply_outbuf(req, 0, 0);
6351
6352         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6353  out:
6354         TALLOC_FREE(smb_dname);
6355         END_PROFILE(SMBmkdir);
6356         return;
6357 }
6358
6359 /****************************************************************************
6360  Reply to a rmdir.
6361 ****************************************************************************/
6362
6363 void reply_rmdir(struct smb_request *req)
6364 {
6365         connection_struct *conn = req->conn;
6366         struct smb_filename *smb_dname = NULL;
6367         char *directory = NULL;
6368         NTSTATUS status;
6369         TALLOC_CTX *ctx = talloc_tos();
6370         files_struct *fsp = NULL;
6371         int info = 0;
6372         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6373         struct smbd_server_connection *sconn = req->sconn;
6374
6375         START_PROFILE(SMBrmdir);
6376
6377         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6378                             STR_TERMINATE, &status);
6379         if (!NT_STATUS_IS_OK(status)) {
6380                 reply_nterror(req, status);
6381                 goto out;
6382         }
6383
6384         status = filename_convert(ctx, conn,
6385                                  directory,
6386                                  ucf_flags,
6387                                  NULL,
6388                                  NULL,
6389                                  &smb_dname);
6390         if (!NT_STATUS_IS_OK(status)) {
6391                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6392                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6393                                         ERRSRV, ERRbadpath);
6394                         goto out;
6395                 }
6396                 reply_nterror(req, status);
6397                 goto out;
6398         }
6399
6400         if (is_ntfs_stream_smb_fname(smb_dname)) {
6401                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6402                 goto out;
6403         }
6404
6405         status = SMB_VFS_CREATE_FILE(
6406                 conn,                                   /* conn */
6407                 req,                                    /* req */
6408                 0,                                      /* root_dir_fid */
6409                 smb_dname,                              /* fname */
6410                 DELETE_ACCESS,                          /* access_mask */
6411                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6412                         FILE_SHARE_DELETE),
6413                 FILE_OPEN,                              /* create_disposition*/
6414                 FILE_DIRECTORY_FILE,                    /* create_options */
6415                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6416                 0,                                      /* oplock_request */
6417                 NULL,                                   /* lease */
6418                 0,                                      /* allocation_size */
6419                 0,                                      /* private_flags */
6420                 NULL,                                   /* sd */
6421                 NULL,                                   /* ea_list */
6422                 &fsp,                                   /* result */
6423                 &info,                                  /* pinfo */
6424                 NULL, NULL);                            /* create context */
6425
6426         if (!NT_STATUS_IS_OK(status)) {
6427                 if (open_was_deferred(req->xconn, req->mid)) {
6428                         /* We have re-scheduled this call. */
6429                         goto out;
6430                 }
6431                 reply_nterror(req, status);
6432                 goto out;
6433         }
6434
6435         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6436         if (!NT_STATUS_IS_OK(status)) {
6437                 close_file(req, fsp, ERROR_CLOSE);
6438                 reply_nterror(req, status);
6439                 goto out;
6440         }
6441
6442         if (!set_delete_on_close(fsp, true,
6443                         conn->session_info->security_token,
6444                         conn->session_info->unix_token)) {
6445                 close_file(req, fsp, ERROR_CLOSE);
6446                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6447                 goto out;
6448         }
6449
6450         status = close_file(req, fsp, NORMAL_CLOSE);
6451         if (!NT_STATUS_IS_OK(status)) {
6452                 reply_nterror(req, status);
6453         } else {
6454                 reply_outbuf(req, 0, 0);
6455         }
6456
6457         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6458
6459         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6460  out:
6461         TALLOC_FREE(smb_dname);
6462         END_PROFILE(SMBrmdir);
6463         return;
6464 }
6465
6466 /*******************************************************************
6467  Resolve wildcards in a filename rename.
6468 ********************************************************************/
6469
6470 static bool resolve_wildcards(TALLOC_CTX *ctx,
6471                                 const char *name1,
6472                                 const char *name2,
6473                                 char **pp_newname)
6474 {
6475         char *name2_copy = NULL;
6476         char *root1 = NULL;
6477         char *root2 = NULL;
6478         char *ext1 = NULL;
6479         char *ext2 = NULL;
6480         char *p,*p2, *pname1, *pname2;
6481
6482         name2_copy = talloc_strdup(ctx, name2);
6483         if (!name2_copy) {
6484                 return False;
6485         }
6486
6487         pname1 = strrchr_m(name1,'/');
6488         pname2 = strrchr_m(name2_copy,'/');
6489
6490         if (!pname1 || !pname2) {
6491                 return False;
6492         }
6493
6494         /* Truncate the copy of name2 at the last '/' */
6495         *pname2 = '\0';
6496
6497         /* Now go past the '/' */
6498         pname1++;
6499         pname2++;
6500
6501         root1 = talloc_strdup(ctx, pname1);
6502         root2 = talloc_strdup(ctx, pname2);
6503
6504         if (!root1 || !root2) {
6505                 return False;
6506         }
6507
6508         p = strrchr_m(root1,'.');
6509         if (p) {
6510                 *p = 0;
6511                 ext1 = talloc_strdup(ctx, p+1);
6512         } else {
6513                 ext1 = talloc_strdup(ctx, "");
6514         }
6515         p = strrchr_m(root2,'.');
6516         if (p) {
6517                 *p = 0;
6518                 ext2 = talloc_strdup(ctx, p+1);
6519         } else {
6520                 ext2 = talloc_strdup(ctx, "");
6521         }
6522
6523         if (!ext1 || !ext2) {
6524                 return False;
6525         }
6526
6527         p = root1;
6528         p2 = root2;
6529         while (*p2) {
6530                 if (*p2 == '?') {
6531                         /* Hmmm. Should this be mb-aware ? */
6532                         *p2 = *p;
6533                         p2++;
6534                 } else if (*p2 == '*') {
6535                         *p2 = '\0';
6536                         root2 = talloc_asprintf(ctx, "%s%s",
6537                                                 root2,
6538                                                 p);
6539                         if (!root2) {
6540                                 return False;
6541                         }
6542                         break;
6543                 } else {
6544                         p2++;
6545                 }
6546                 if (*p) {
6547                         p++;
6548                 }
6549         }
6550
6551         p = ext1;
6552         p2 = ext2;
6553         while (*p2) {
6554                 if (*p2 == '?') {
6555                         /* Hmmm. Should this be mb-aware ? */
6556                         *p2 = *p;
6557                         p2++;
6558                 } else if (*p2 == '*') {
6559                         *p2 = '\0';
6560                         ext2 = talloc_asprintf(ctx, "%s%s",
6561                                                 ext2,
6562                                                 p);
6563                         if (!ext2) {
6564                                 return False;
6565                         }
6566                         break;
6567                 } else {
6568                         p2++;
6569                 }
6570                 if (*p) {
6571                         p++;
6572                 }
6573         }
6574
6575         if (*ext2) {
6576                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6577                                 name2_copy,
6578                                 root2,
6579                                 ext2);
6580         } else {
6581                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6582                                 name2_copy,
6583                                 root2);
6584         }
6585
6586         if (!*pp_newname) {
6587                 return False;
6588         }
6589
6590         return True;
6591 }
6592
6593 /****************************************************************************
6594  Ensure open files have their names updated. Updated to notify other smbd's
6595  asynchronously.
6596 ****************************************************************************/
6597
6598 static void rename_open_files(connection_struct *conn,
6599                               struct share_mode_lock *lck,
6600                               struct file_id id,
6601                               uint32_t orig_name_hash,
6602                               const struct smb_filename *smb_fname_dst)
6603 {
6604         files_struct *fsp;
6605         bool did_rename = False;
6606         NTSTATUS status;
6607         uint32_t new_name_hash = 0;
6608
6609         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6610             fsp = file_find_di_next(fsp)) {
6611                 /* fsp_name is a relative path under the fsp. To change this for other
6612                    sharepaths we need to manipulate relative paths. */
6613                 /* TODO - create the absolute path and manipulate the newname
6614                    relative to the sharepath. */
6615                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6616                         continue;
6617                 }
6618                 if (fsp->name_hash != orig_name_hash) {
6619                         continue;
6620                 }
6621                 DEBUG(10, ("rename_open_files: renaming file %s "
6622                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6623                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6624                            smb_fname_str_dbg(smb_fname_dst)));
6625
6626                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6627                 if (NT_STATUS_IS_OK(status)) {
6628                         did_rename = True;
6629                         new_name_hash = fsp->name_hash;
6630                 }
6631         }
6632
6633         if (!did_rename) {
6634                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6635                            "for %s\n", file_id_string_tos(&id),
6636                            smb_fname_str_dbg(smb_fname_dst)));
6637         }
6638
6639         /* Send messages to all smbd's (not ourself) that the name has changed. */
6640         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6641                               orig_name_hash, new_name_hash,
6642                               smb_fname_dst);
6643
6644 }
6645
6646 /****************************************************************************
6647  We need to check if the source path is a parent directory of the destination
6648  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6649  refuse the rename with a sharing violation. Under UNIX the above call can
6650  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6651  probably need to check that the client is a Windows one before disallowing
6652  this as a UNIX client (one with UNIX extensions) can know the source is a
6653  symlink and make this decision intelligently. Found by an excellent bug
6654  report from <AndyLiebman@aol.com>.
6655 ****************************************************************************/
6656
6657 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6658                                      const struct smb_filename *smb_fname_dst)
6659 {
6660         const char *psrc = smb_fname_src->base_name;
6661         const char *pdst = smb_fname_dst->base_name;
6662         size_t slen;
6663
6664         if (psrc[0] == '.' && psrc[1] == '/') {
6665                 psrc += 2;
6666         }
6667         if (pdst[0] == '.' && pdst[1] == '/') {
6668                 pdst += 2;
6669         }
6670         if ((slen = strlen(psrc)) > strlen(pdst)) {
6671                 return False;
6672         }
6673         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6674 }
6675
6676 /*
6677  * Do the notify calls from a rename
6678  */
6679
6680 static void notify_rename(connection_struct *conn, bool is_dir,
6681                           const struct smb_filename *smb_fname_src,
6682                           const struct smb_filename *smb_fname_dst)
6683 {
6684         char *parent_dir_src = NULL;
6685         char *parent_dir_dst = NULL;
6686         uint32_t mask;
6687
6688         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6689                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6690
6691         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6692                             &parent_dir_src, NULL) ||
6693             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6694                             &parent_dir_dst, NULL)) {
6695                 goto out;
6696         }
6697
6698         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6699                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6700                              smb_fname_src->base_name);
6701                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6702                              smb_fname_dst->base_name);
6703         }
6704         else {
6705                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6706                              smb_fname_src->base_name);
6707                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6708                              smb_fname_dst->base_name);
6709         }
6710
6711         /* this is a strange one. w2k3 gives an additional event for
6712            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6713            files, but not directories */
6714         if (!is_dir) {
6715                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6716                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6717                              |FILE_NOTIFY_CHANGE_CREATION,
6718                              smb_fname_dst->base_name);
6719         }
6720  out:
6721         TALLOC_FREE(parent_dir_src);
6722         TALLOC_FREE(parent_dir_dst);
6723 }
6724
6725 /****************************************************************************
6726  Returns an error if the parent directory for a filename is open in an
6727  incompatible way.
6728 ****************************************************************************/
6729
6730 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6731                                         const struct smb_filename *smb_fname_dst_in)
6732 {
6733         char *parent_dir = NULL;
6734         struct smb_filename smb_fname_parent;
6735         struct file_id id;
6736         files_struct *fsp = NULL;
6737         int ret;
6738
6739         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6740                         &parent_dir, NULL)) {
6741                 return NT_STATUS_NO_MEMORY;
6742         }
6743         ZERO_STRUCT(smb_fname_parent);
6744         smb_fname_parent.base_name = parent_dir;
6745
6746         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6747         if (ret == -1) {
6748                 return map_nt_error_from_unix(errno);
6749         }
6750
6751         /*
6752          * We're only checking on this smbd here, mostly good
6753          * enough.. and will pass tests.
6754          */
6755
6756         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6757         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6758                         fsp = file_find_di_next(fsp)) {
6759                 if (fsp->access_mask & DELETE_ACCESS) {
6760                         return NT_STATUS_SHARING_VIOLATION;
6761                 }
6762         }
6763         return NT_STATUS_OK;
6764 }
6765
6766 /****************************************************************************
6767  Rename an open file - given an fsp.
6768 ****************************************************************************/
6769
6770 NTSTATUS rename_internals_fsp(connection_struct *conn,
6771                         files_struct *fsp,
6772                         const struct smb_filename *smb_fname_dst_in,
6773                         uint32_t attrs,
6774                         bool replace_if_exists)
6775 {
6776         TALLOC_CTX *ctx = talloc_tos();
6777         struct smb_filename *smb_fname_dst = NULL;
6778         NTSTATUS status = NT_STATUS_OK;
6779         struct share_mode_lock *lck = NULL;
6780         uint32_t access_mask = SEC_DIR_ADD_FILE;
6781         bool dst_exists, old_is_stream, new_is_stream;
6782
6783         status = check_name(conn, smb_fname_dst_in);
6784         if (!NT_STATUS_IS_OK(status)) {
6785                 return status;
6786         }
6787
6788         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6789         if (!NT_STATUS_IS_OK(status)) {
6790                 return status;
6791         }
6792
6793         if (file_has_open_streams(fsp)) {
6794                 return NT_STATUS_ACCESS_DENIED;
6795         }
6796
6797         /* Make a copy of the dst smb_fname structs */
6798
6799         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6800         if (smb_fname_dst == NULL) {
6801                 status = NT_STATUS_NO_MEMORY;
6802                 goto out;
6803         }
6804
6805         /*
6806          * Check for special case with case preserving and not
6807          * case sensitive. If the new last component differs from the original
6808          * last component only by case, then we should allow
6809          * the rename (user is trying to change the case of the
6810          * filename).
6811          */
6812         if (!conn->case_sensitive && conn->case_preserve &&
6813             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6814             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6815                 char *fname_dst_parent = NULL;
6816                 const char *fname_dst_lcomp = NULL;
6817                 char *orig_lcomp_path = NULL;
6818                 char *orig_lcomp_stream = NULL;
6819                 bool ok = true;
6820
6821                 /*
6822                  * Split off the last component of the processed
6823                  * destination name. We will compare this to
6824                  * the split components of smb_fname_dst->original_lcomp.
6825                  */
6826                 if (!parent_dirname(ctx,
6827                                 smb_fname_dst->base_name,
6828                                 &fname_dst_parent,
6829                                 &fname_dst_lcomp)) {
6830                         status = NT_STATUS_NO_MEMORY;
6831                         goto out;
6832                 }
6833
6834                 /*
6835                  * The original_lcomp component contains
6836                  * the last_component of the path + stream
6837                  * name (if a stream exists).
6838                  *
6839                  * Split off the stream name so we
6840                  * can check them separately.
6841                  */
6842
6843                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6844                         /* POSIX - no stream component. */
6845                         orig_lcomp_path = talloc_strdup(ctx,
6846                                                 smb_fname_dst->original_lcomp);
6847                         if (orig_lcomp_path == NULL) {
6848                                 ok = false;
6849                         }
6850                 } else {
6851                         ok = split_stream_filename(ctx,
6852                                         smb_fname_dst->original_lcomp,
6853                                         &orig_lcomp_path,
6854                                         &orig_lcomp_stream);
6855                 }
6856
6857                 if (!ok) {
6858                         TALLOC_FREE(fname_dst_parent);
6859                         status = NT_STATUS_NO_MEMORY;
6860                         goto out;
6861                 }
6862
6863                 /* If the base names only differ by case, use original. */
6864                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6865                         char *tmp;
6866                         /*
6867                          * Replace the modified last component with the
6868                          * original.
6869                          */
6870                         if (!ISDOT(fname_dst_parent)) {
6871                                 tmp = talloc_asprintf(smb_fname_dst,
6872                                         "%s/%s",
6873                                         fname_dst_parent,
6874                                         orig_lcomp_path);
6875                         } else {
6876                                 tmp = talloc_strdup(smb_fname_dst,
6877                                         orig_lcomp_path);
6878                         }
6879                         if (tmp == NULL) {
6880                                 status = NT_STATUS_NO_MEMORY;
6881                                 TALLOC_FREE(fname_dst_parent);
6882                                 TALLOC_FREE(orig_lcomp_path);
6883                                 TALLOC_FREE(orig_lcomp_stream);
6884                                 goto out;
6885                         }
6886                         TALLOC_FREE(smb_fname_dst->base_name);
6887                         smb_fname_dst->base_name = tmp;
6888                 }
6889
6890                 /* If the stream_names only differ by case, use original. */
6891                 if(!strcsequal(smb_fname_dst->stream_name,
6892                                orig_lcomp_stream)) {
6893                         /* Use the original stream. */
6894                         char *tmp = talloc_strdup(smb_fname_dst,
6895                                             orig_lcomp_stream);
6896                         if (tmp == NULL) {
6897                                 status = NT_STATUS_NO_MEMORY;
6898                                 TALLOC_FREE(fname_dst_parent);
6899                                 TALLOC_FREE(orig_lcomp_path);
6900                                 TALLOC_FREE(orig_lcomp_stream);
6901                                 goto out;
6902                         }
6903                         TALLOC_FREE(smb_fname_dst->stream_name);
6904                         smb_fname_dst->stream_name = tmp;
6905                 }
6906                 TALLOC_FREE(fname_dst_parent);
6907                 TALLOC_FREE(orig_lcomp_path);
6908                 TALLOC_FREE(orig_lcomp_stream);
6909         }
6910
6911         /*
6912          * If the src and dest names are identical - including case,
6913          * don't do the rename, just return success.
6914          */
6915
6916         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6917             strcsequal(fsp->fsp_name->stream_name,
6918                        smb_fname_dst->stream_name)) {
6919                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6920                           "- returning success\n",
6921                           smb_fname_str_dbg(smb_fname_dst)));
6922                 status = NT_STATUS_OK;
6923                 goto out;
6924         }
6925
6926         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6927         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6928
6929         /* Return the correct error code if both names aren't streams. */
6930         if (!old_is_stream && new_is_stream) {
6931                 status = NT_STATUS_OBJECT_NAME_INVALID;
6932                 goto out;
6933         }
6934
6935         if (old_is_stream && !new_is_stream) {
6936                 status = NT_STATUS_INVALID_PARAMETER;
6937                 goto out;
6938         }
6939
6940         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6941
6942         if(!replace_if_exists && dst_exists) {
6943                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6944                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6945                           smb_fname_str_dbg(smb_fname_dst)));
6946                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6947                 goto out;
6948         }
6949
6950         if (dst_exists) {
6951                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6952                     &smb_fname_dst->st);
6953                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6954                                                            fileid);
6955                 /* The file can be open when renaming a stream */
6956                 if (dst_fsp && !new_is_stream) {
6957                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6958                         status = NT_STATUS_ACCESS_DENIED;
6959                         goto out;
6960                 }
6961         }
6962
6963         /* Ensure we have a valid stat struct for the source. */
6964         status = vfs_stat_fsp(fsp);
6965         if (!NT_STATUS_IS_OK(status)) {
6966                 goto out;
6967         }
6968
6969         status = can_rename(conn, fsp, attrs);
6970
6971         if (!NT_STATUS_IS_OK(status)) {
6972                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6973                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6974                           smb_fname_str_dbg(smb_fname_dst)));
6975                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6976                         status = NT_STATUS_ACCESS_DENIED;
6977                 goto out;
6978         }
6979
6980         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6981                 status = NT_STATUS_ACCESS_DENIED;
6982                 goto out;
6983         }
6984
6985         /* Do we have rights to move into the destination ? */
6986         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6987                 /* We're moving a directory. */
6988                 access_mask = SEC_DIR_ADD_SUBDIR;
6989         }
6990         status = check_parent_access(conn,
6991                                 smb_fname_dst,
6992                                 access_mask);
6993         if (!NT_STATUS_IS_OK(status)) {
6994                 DBG_INFO("check_parent_access on "
6995                         "dst %s returned %s\n",
6996                         smb_fname_str_dbg(smb_fname_dst),
6997                         nt_errstr(status));
6998                 goto out;
6999         }
7000
7001         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7002
7003         /*
7004          * We have the file open ourselves, so not being able to get the
7005          * corresponding share mode lock is a fatal error.
7006          */
7007
7008         SMB_ASSERT(lck != NULL);
7009
7010         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
7011                 uint32_t create_options = fsp->fh->private_options;
7012
7013                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7014                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7015                           smb_fname_str_dbg(smb_fname_dst)));
7016
7017                 if (!fsp->is_directory &&
7018                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7019                     (lp_map_archive(SNUM(conn)) ||
7020                     lp_store_dos_attributes(SNUM(conn)))) {
7021                         /* We must set the archive bit on the newly
7022                            renamed file. */
7023                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7024                                 uint32_t old_dosmode = dos_mode(conn,
7025                                                         smb_fname_dst);
7026                                 file_set_dosmode(conn,
7027                                         smb_fname_dst,
7028                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7029                                         NULL,
7030                                         true);
7031                         }
7032                 }
7033
7034                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7035                               smb_fname_dst);
7036
7037                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7038                                   smb_fname_dst);
7039
7040                 /*
7041                  * A rename acts as a new file create w.r.t. allowing an initial delete
7042                  * on close, probably because in Windows there is a new handle to the
7043                  * new file. If initial delete on close was requested but not
7044                  * originally set, we need to set it here. This is probably not 100% correct,
7045                  * but will work for the CIFSFS client which in non-posix mode
7046                  * depends on these semantics. JRA.
7047                  */
7048
7049                 if (create_options & FILE_DELETE_ON_CLOSE) {
7050                         status = can_set_delete_on_close(fsp, 0);
7051
7052                         if (NT_STATUS_IS_OK(status)) {
7053                                 /* Note that here we set the *initial* delete on close flag,
7054                                  * not the regular one. The magic gets handled in close. */
7055                                 fsp->initial_delete_on_close = True;
7056                         }
7057                 }
7058                 TALLOC_FREE(lck);
7059                 status = NT_STATUS_OK;
7060                 goto out;
7061         }
7062
7063         TALLOC_FREE(lck);
7064
7065         if (errno == ENOTDIR || errno == EISDIR) {
7066                 status = NT_STATUS_OBJECT_NAME_COLLISION;
7067         } else {
7068                 status = map_nt_error_from_unix(errno);
7069         }
7070
7071         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7072                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7073                   smb_fname_str_dbg(smb_fname_dst)));
7074
7075  out:
7076         TALLOC_FREE(smb_fname_dst);
7077
7078         return status;
7079 }
7080
7081 /****************************************************************************
7082  The guts of the rename command, split out so it may be called by the NT SMB
7083  code.
7084 ****************************************************************************/
7085
7086 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7087                         connection_struct *conn,
7088                         struct smb_request *req,
7089                         struct smb_filename *smb_fname_src,
7090                         struct smb_filename *smb_fname_dst,
7091                         uint32_t attrs,
7092                         bool replace_if_exists,
7093                         bool src_has_wild,
7094                         bool dest_has_wild,
7095                         uint32_t access_mask)
7096 {
7097         char *fname_src_dir = NULL;
7098         struct smb_filename *smb_fname_src_dir = NULL;
7099         char *fname_src_mask = NULL;
7100         int count=0;
7101         NTSTATUS status = NT_STATUS_OK;
7102         struct smb_Dir *dir_hnd = NULL;
7103         const char *dname = NULL;
7104         char *talloced = NULL;
7105         long offset = 0;
7106         int create_options = 0;
7107         bool posix_pathnames = (req != NULL && req->posix_pathnames);
7108         int rc;
7109
7110         /*
7111          * Split the old name into directory and last component
7112          * strings. Note that unix_convert may have stripped off a
7113          * leading ./ from both name and newname if the rename is
7114          * at the root of the share. We need to make sure either both
7115          * name and newname contain a / character or neither of them do
7116          * as this is checked in resolve_wildcards().
7117          */
7118
7119         /* Split up the directory from the filename/mask. */
7120         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7121                                       &fname_src_dir, &fname_src_mask);
7122         if (!NT_STATUS_IS_OK(status)) {
7123                 status = NT_STATUS_NO_MEMORY;
7124                 goto out;
7125         }
7126
7127         /*
7128          * We should only check the mangled cache
7129          * here if unix_convert failed. This means
7130          * that the path in 'mask' doesn't exist
7131          * on the file system and so we need to look
7132          * for a possible mangle. This patch from
7133          * Tine Smukavec <valentin.smukavec@hermes.si>.
7134          */
7135
7136         if (!VALID_STAT(smb_fname_src->st) &&
7137             mangle_is_mangled(fname_src_mask, conn->params)) {
7138                 char *new_mask = NULL;
7139                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7140                                             conn->params);
7141                 if (new_mask) {
7142                         TALLOC_FREE(fname_src_mask);
7143                         fname_src_mask = new_mask;
7144                 }
7145         }
7146
7147         if (!src_has_wild) {
7148                 files_struct *fsp;
7149
7150                 /*
7151                  * Only one file needs to be renamed. Append the mask back
7152                  * onto the directory.
7153                  */
7154                 TALLOC_FREE(smb_fname_src->base_name);
7155                 if (ISDOT(fname_src_dir)) {
7156                         /* Ensure we use canonical names on open. */
7157                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7158                                                         "%s",
7159                                                         fname_src_mask);
7160                 } else {
7161                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7162                                                         "%s/%s",
7163                                                         fname_src_dir,
7164                                                         fname_src_mask);
7165                 }
7166                 if (!smb_fname_src->base_name) {
7167                         status = NT_STATUS_NO_MEMORY;
7168                         goto out;
7169                 }
7170
7171                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7172                           "case_preserve = %d, short case preserve = %d, "
7173                           "directory = %s, newname = %s, "
7174                           "last_component_dest = %s\n",
7175                           conn->case_sensitive, conn->case_preserve,
7176                           conn->short_case_preserve,
7177                           smb_fname_str_dbg(smb_fname_src),
7178                           smb_fname_str_dbg(smb_fname_dst),
7179                           smb_fname_dst->original_lcomp));
7180
7181                 /* The dest name still may have wildcards. */
7182                 if (dest_has_wild) {
7183                         char *fname_dst_mod = NULL;
7184                         if (!resolve_wildcards(smb_fname_dst,
7185                                                smb_fname_src->base_name,
7186                                                smb_fname_dst->base_name,
7187                                                &fname_dst_mod)) {
7188                                 DEBUG(6, ("rename_internals: resolve_wildcards "
7189                                           "%s %s failed\n",
7190                                           smb_fname_src->base_name,
7191                                           smb_fname_dst->base_name));
7192                                 status = NT_STATUS_NO_MEMORY;
7193                                 goto out;
7194                         }
7195                         TALLOC_FREE(smb_fname_dst->base_name);
7196                         smb_fname_dst->base_name = fname_dst_mod;
7197                 }
7198
7199                 ZERO_STRUCT(smb_fname_src->st);
7200                 if (posix_pathnames) {
7201                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7202                 } else {
7203                         rc = SMB_VFS_STAT(conn, smb_fname_src);
7204                 }
7205                 if (rc == -1) {
7206                         status = map_nt_error_from_unix_common(errno);
7207                         goto out;
7208                 }
7209
7210                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7211                         create_options |= FILE_DIRECTORY_FILE;
7212                 }
7213
7214                 status = SMB_VFS_CREATE_FILE(
7215                         conn,                           /* conn */
7216                         req,                            /* req */
7217                         0,                              /* root_dir_fid */
7218                         smb_fname_src,                  /* fname */
7219                         access_mask,                    /* access_mask */
7220                         (FILE_SHARE_READ |              /* share_access */
7221                             FILE_SHARE_WRITE),
7222                         FILE_OPEN,                      /* create_disposition*/
7223                         create_options,                 /* create_options */
7224                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7225                         0,                              /* oplock_request */
7226                         NULL,                           /* lease */
7227                         0,                              /* allocation_size */
7228                         0,                              /* private_flags */
7229                         NULL,                           /* sd */
7230                         NULL,                           /* ea_list */
7231                         &fsp,                           /* result */
7232                         NULL,                           /* pinfo */
7233                         NULL, NULL);                    /* create context */
7234
7235                 if (!NT_STATUS_IS_OK(status)) {
7236                         DEBUG(3, ("Could not open rename source %s: %s\n",
7237                                   smb_fname_str_dbg(smb_fname_src),
7238                                   nt_errstr(status)));
7239                         goto out;
7240                 }
7241
7242                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7243                                               attrs, replace_if_exists);
7244
7245                 close_file(req, fsp, NORMAL_CLOSE);
7246
7247                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7248                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7249                           smb_fname_str_dbg(smb_fname_dst)));
7250
7251                 goto out;
7252         }
7253
7254         /*
7255          * Wildcards - process each file that matches.
7256          */
7257         if (strequal(fname_src_mask, "????????.???")) {
7258                 TALLOC_FREE(fname_src_mask);
7259                 fname_src_mask = talloc_strdup(ctx, "*");
7260                 if (!fname_src_mask) {
7261                         status = NT_STATUS_NO_MEMORY;
7262                         goto out;
7263                 }
7264         }
7265
7266         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7267                                 fname_src_dir,
7268                                 NULL,
7269                                 NULL,
7270                                 smb_fname_src->flags);
7271         if (smb_fname_src_dir == NULL) {
7272                 status = NT_STATUS_NO_MEMORY;
7273                 goto out;
7274         }
7275
7276         status = check_name(conn, smb_fname_src_dir);
7277         if (!NT_STATUS_IS_OK(status)) {
7278                 goto out;
7279         }
7280
7281         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7282                           attrs);
7283         if (dir_hnd == NULL) {
7284                 status = map_nt_error_from_unix(errno);
7285                 goto out;
7286         }
7287
7288         status = NT_STATUS_NO_SUCH_FILE;
7289         /*
7290          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7291          * - gentest fix. JRA
7292          */
7293
7294         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7295                                     &talloced))) {
7296                 files_struct *fsp = NULL;
7297                 char *destname = NULL;
7298                 bool sysdir_entry = False;
7299
7300                 /* Quick check for "." and ".." */
7301                 if (ISDOT(dname) || ISDOTDOT(dname)) {
7302                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7303                                 sysdir_entry = True;
7304                         } else {
7305                                 TALLOC_FREE(talloced);
7306                                 continue;
7307                         }
7308                 }
7309
7310                 if (!is_visible_file(conn, fname_src_dir, dname,
7311                                      &smb_fname_src->st, false)) {
7312                         TALLOC_FREE(talloced);
7313                         continue;
7314                 }
7315
7316                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7317                         TALLOC_FREE(talloced);
7318                         continue;
7319                 }
7320
7321                 if (sysdir_entry) {
7322                         status = NT_STATUS_OBJECT_NAME_INVALID;
7323                         break;
7324                 }
7325
7326                 TALLOC_FREE(smb_fname_src->base_name);
7327                 if (ISDOT(fname_src_dir)) {
7328                         /* Ensure we use canonical names on open. */
7329                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7330                                                         "%s",
7331                                                         dname);
7332                 } else {
7333                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7334                                                         "%s/%s",
7335                                                         fname_src_dir,
7336                                                         dname);
7337                 }
7338                 if (!smb_fname_src->base_name) {
7339                         status = NT_STATUS_NO_MEMORY;
7340                         goto out;
7341                 }
7342
7343                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7344                                        smb_fname_dst->base_name,
7345                                        &destname)) {
7346                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
7347                                   smb_fname_src->base_name, destname));
7348                         TALLOC_FREE(talloced);
7349                         continue;
7350                 }
7351                 if (!destname) {
7352                         status = NT_STATUS_NO_MEMORY;
7353                         goto out;
7354                 }
7355
7356                 TALLOC_FREE(smb_fname_dst->base_name);
7357                 smb_fname_dst->base_name = destname;
7358
7359                 ZERO_STRUCT(smb_fname_src->st);
7360                 if (posix_pathnames) {
7361                         SMB_VFS_LSTAT(conn, smb_fname_src);
7362                 } else {
7363                         SMB_VFS_STAT(conn, smb_fname_src);
7364                 }
7365
7366                 create_options = 0;
7367
7368                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7369                         create_options |= FILE_DIRECTORY_FILE;
7370                 }
7371
7372                 status = SMB_VFS_CREATE_FILE(
7373                         conn,                           /* conn */
7374                         req,                            /* req */
7375                         0,                              /* root_dir_fid */
7376                         smb_fname_src,                  /* fname */
7377                         access_mask,                    /* access_mask */
7378                         (FILE_SHARE_READ |              /* share_access */
7379                             FILE_SHARE_WRITE),
7380                         FILE_OPEN,                      /* create_disposition*/
7381                         create_options,                 /* create_options */
7382                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7383                         0,                              /* oplock_request */
7384                         NULL,                           /* lease */
7385                         0,                              /* allocation_size */
7386                         0,                              /* private_flags */
7387                         NULL,                           /* sd */
7388                         NULL,                           /* ea_list */
7389                         &fsp,                           /* result */
7390                         NULL,                           /* pinfo */
7391                         NULL, NULL);                    /* create context */
7392
7393                 if (!NT_STATUS_IS_OK(status)) {
7394                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7395                                  "returned %s rename %s -> %s\n",
7396                                  nt_errstr(status),
7397                                  smb_fname_str_dbg(smb_fname_src),
7398                                  smb_fname_str_dbg(smb_fname_dst)));
7399                         break;
7400                 }
7401
7402                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7403                                                               dname);
7404                 if (!smb_fname_dst->original_lcomp) {
7405                         status = NT_STATUS_NO_MEMORY;
7406                         goto out;
7407                 }
7408
7409                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7410                                               attrs, replace_if_exists);
7411
7412                 close_file(req, fsp, NORMAL_CLOSE);
7413
7414                 if (!NT_STATUS_IS_OK(status)) {
7415                         DEBUG(3, ("rename_internals_fsp returned %s for "
7416                                   "rename %s -> %s\n", nt_errstr(status),
7417                                   smb_fname_str_dbg(smb_fname_src),
7418                                   smb_fname_str_dbg(smb_fname_dst)));
7419                         break;
7420                 }
7421
7422                 count++;
7423
7424                 DEBUG(3,("rename_internals: doing rename on %s -> "
7425                          "%s\n", smb_fname_str_dbg(smb_fname_src),
7426                          smb_fname_str_dbg(smb_fname_src)));
7427                 TALLOC_FREE(talloced);
7428         }
7429         TALLOC_FREE(dir_hnd);
7430
7431         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7432                 status = map_nt_error_from_unix(errno);
7433         }
7434
7435  out:
7436         TALLOC_FREE(talloced);
7437         TALLOC_FREE(smb_fname_src_dir);
7438         TALLOC_FREE(fname_src_dir);
7439         TALLOC_FREE(fname_src_mask);
7440         return status;
7441 }
7442
7443 /****************************************************************************
7444  Reply to a mv.
7445 ****************************************************************************/
7446
7447 void reply_mv(struct smb_request *req)
7448 {
7449         connection_struct *conn = req->conn;
7450         char *name = NULL;
7451         char *newname = NULL;
7452         const char *p;
7453         uint32_t attrs;
7454         NTSTATUS status;
7455         bool src_has_wcard = False;
7456         bool dest_has_wcard = False;
7457         TALLOC_CTX *ctx = talloc_tos();
7458         struct smb_filename *smb_fname_src = NULL;
7459         struct smb_filename *smb_fname_dst = NULL;
7460         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7461                 (req->posix_pathnames ?
7462                         UCF_UNIX_NAME_LOOKUP :
7463                         UCF_COND_ALLOW_WCARD_LCOMP);
7464         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7465                 UCF_SAVE_LCOMP |
7466                 (req->posix_pathnames ?
7467                         0 :
7468                         UCF_COND_ALLOW_WCARD_LCOMP);
7469         bool stream_rename = false;
7470
7471         START_PROFILE(SMBmv);
7472
7473         if (req->wct < 1) {
7474                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7475                 goto out;
7476         }
7477
7478         attrs = SVAL(req->vwv+0, 0);
7479
7480         p = (const char *)req->buf + 1;
7481         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7482                                        &status, &src_has_wcard);
7483         if (!NT_STATUS_IS_OK(status)) {
7484                 reply_nterror(req, status);
7485                 goto out;
7486         }
7487         p++;
7488         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7489                                        &status, &dest_has_wcard);
7490         if (!NT_STATUS_IS_OK(status)) {
7491                 reply_nterror(req, status);
7492                 goto out;
7493         }
7494
7495         if (!req->posix_pathnames) {
7496                 /* The newname must begin with a ':' if the
7497                    name contains a ':'. */
7498                 if (strchr_m(name, ':')) {
7499                         if (newname[0] != ':') {
7500                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7501                                 goto out;
7502                         }
7503                         stream_rename = true;
7504                 }
7505         }
7506
7507         status = filename_convert(ctx,
7508                                   conn,
7509                                   name,
7510                                   src_ucf_flags,
7511                                   NULL,
7512                                   &src_has_wcard,
7513                                   &smb_fname_src);
7514
7515         if (!NT_STATUS_IS_OK(status)) {
7516                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7517                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7518                                         ERRSRV, ERRbadpath);
7519                         goto out;
7520                 }
7521                 reply_nterror(req, status);
7522                 goto out;
7523         }
7524
7525         status = filename_convert(ctx,
7526                                   conn,
7527                                   newname,
7528                                   dst_ucf_flags,
7529                                   NULL,
7530                                   &dest_has_wcard,
7531                                   &smb_fname_dst);
7532
7533         if (!NT_STATUS_IS_OK(status)) {
7534                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7535                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7536                                         ERRSRV, ERRbadpath);
7537                         goto out;
7538                 }
7539                 reply_nterror(req, status);
7540                 goto out;
7541         }
7542
7543         if (stream_rename) {
7544                 /* smb_fname_dst->base_name must be the same as
7545                    smb_fname_src->base_name. */
7546                 TALLOC_FREE(smb_fname_dst->base_name);
7547                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7548                                                 smb_fname_src->base_name);
7549                 if (!smb_fname_dst->base_name) {
7550                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7551                         goto out;
7552                 }
7553         }
7554
7555         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7556                  smb_fname_str_dbg(smb_fname_dst)));
7557
7558         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7559                                   attrs, False, src_has_wcard, dest_has_wcard,
7560                                   DELETE_ACCESS);
7561         if (!NT_STATUS_IS_OK(status)) {
7562                 if (open_was_deferred(req->xconn, req->mid)) {
7563                         /* We have re-scheduled this call. */
7564                         goto out;
7565                 }
7566                 reply_nterror(req, status);
7567                 goto out;
7568         }
7569
7570         reply_outbuf(req, 0, 0);
7571  out:
7572         TALLOC_FREE(smb_fname_src);
7573         TALLOC_FREE(smb_fname_dst);
7574         END_PROFILE(SMBmv);
7575         return;
7576 }
7577
7578 /*******************************************************************
7579  Copy a file as part of a reply_copy.
7580 ******************************************************************/
7581
7582 /*
7583  * TODO: check error codes on all callers
7584  */
7585
7586 NTSTATUS copy_file(TALLOC_CTX *ctx,
7587                         connection_struct *conn,
7588                         struct smb_filename *smb_fname_src,
7589                         struct smb_filename *smb_fname_dst,
7590                         int ofun,
7591                         int count,
7592                         bool target_is_directory)
7593 {
7594         struct smb_filename *smb_fname_dst_tmp = NULL;
7595         off_t ret=-1;
7596         files_struct *fsp1,*fsp2;
7597         uint32_t dosattrs;
7598         uint32_t new_create_disposition;
7599         NTSTATUS status;
7600
7601
7602         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7603         if (smb_fname_dst_tmp == NULL) {
7604                 return NT_STATUS_NO_MEMORY;
7605         }
7606
7607         /*
7608          * If the target is a directory, extract the last component from the
7609          * src filename and append it to the dst filename
7610          */
7611         if (target_is_directory) {
7612                 const char *p;
7613
7614                 /* dest/target can't be a stream if it's a directory. */
7615                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7616
7617                 p = strrchr_m(smb_fname_src->base_name,'/');
7618                 if (p) {
7619                         p++;
7620                 } else {
7621                         p = smb_fname_src->base_name;
7622                 }
7623                 smb_fname_dst_tmp->base_name =
7624                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7625                                            p);
7626                 if (!smb_fname_dst_tmp->base_name) {
7627                         status = NT_STATUS_NO_MEMORY;
7628                         goto out;
7629                 }
7630         }
7631
7632         status = vfs_file_exist(conn, smb_fname_src);
7633         if (!NT_STATUS_IS_OK(status)) {
7634                 goto out;
7635         }
7636
7637         if (!target_is_directory && count) {
7638                 new_create_disposition = FILE_OPEN;
7639         } else {
7640                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7641                                                  0, ofun,
7642                                                  NULL, NULL,
7643                                                  &new_create_disposition,
7644                                                  NULL,
7645                                                  NULL)) {
7646                         status = NT_STATUS_INVALID_PARAMETER;
7647                         goto out;
7648                 }
7649         }
7650
7651         /* Open the src file for reading. */
7652         status = SMB_VFS_CREATE_FILE(
7653                 conn,                                   /* conn */
7654                 NULL,                                   /* req */
7655                 0,                                      /* root_dir_fid */
7656                 smb_fname_src,                          /* fname */
7657                 FILE_GENERIC_READ,                      /* access_mask */
7658                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7659                 FILE_OPEN,                              /* create_disposition*/
7660                 0,                                      /* create_options */
7661                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7662                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7663                 NULL,                                   /* lease */
7664                 0,                                      /* allocation_size */
7665                 0,                                      /* private_flags */
7666                 NULL,                                   /* sd */
7667                 NULL,                                   /* ea_list */
7668                 &fsp1,                                  /* result */
7669                 NULL,                                   /* psbuf */
7670                 NULL, NULL);                            /* create context */
7671
7672         if (!NT_STATUS_IS_OK(status)) {
7673                 goto out;
7674         }
7675
7676         dosattrs = dos_mode(conn, smb_fname_src);
7677
7678         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7679                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7680         }
7681
7682         /* Open the dst file for writing. */
7683         status = SMB_VFS_CREATE_FILE(
7684                 conn,                                   /* conn */
7685                 NULL,                                   /* req */
7686                 0,                                      /* root_dir_fid */
7687                 smb_fname_dst,                          /* fname */
7688                 FILE_GENERIC_WRITE,                     /* access_mask */
7689                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7690                 new_create_disposition,                 /* create_disposition*/
7691                 0,                                      /* create_options */
7692                 dosattrs,                               /* file_attributes */
7693                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7694                 NULL,                                   /* lease */
7695                 0,                                      /* allocation_size */
7696                 0,                                      /* private_flags */
7697                 NULL,                                   /* sd */
7698                 NULL,                                   /* ea_list */
7699                 &fsp2,                                  /* result */
7700                 NULL,                                   /* psbuf */
7701                 NULL, NULL);                            /* create context */
7702
7703         if (!NT_STATUS_IS_OK(status)) {
7704                 close_file(NULL, fsp1, ERROR_CLOSE);
7705                 goto out;
7706         }
7707
7708         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7709                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7710                 if (ret == -1) {
7711                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7712                                 strerror(errno)));
7713                         status = map_nt_error_from_unix(errno);
7714                         close_file(NULL, fsp1, ERROR_CLOSE);
7715                         close_file(NULL, fsp2, ERROR_CLOSE);
7716                         goto out;
7717                 }
7718         }
7719
7720         /* Do the actual copy. */
7721         if (smb_fname_src->st.st_ex_size) {
7722                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7723         } else {
7724                 ret = 0;
7725         }
7726
7727         close_file(NULL, fsp1, NORMAL_CLOSE);
7728
7729         /* Ensure the modtime is set correctly on the destination file. */
7730         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7731
7732         /*
7733          * As we are opening fsp1 read-only we only expect
7734          * an error on close on fsp2 if we are out of space.
7735          * Thus we don't look at the error return from the
7736          * close of fsp1.
7737          */
7738         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7739
7740         if (!NT_STATUS_IS_OK(status)) {
7741                 goto out;
7742         }
7743
7744         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7745                 status = NT_STATUS_DISK_FULL;
7746                 goto out;
7747         }
7748
7749         status = NT_STATUS_OK;
7750
7751  out:
7752         TALLOC_FREE(smb_fname_dst_tmp);
7753         return status;
7754 }
7755
7756 /****************************************************************************
7757  Reply to a file copy.
7758 ****************************************************************************/
7759
7760 void reply_copy(struct smb_request *req)
7761 {
7762         connection_struct *conn = req->conn;
7763         struct smb_filename *smb_fname_src = NULL;
7764         struct smb_filename *smb_fname_src_dir = NULL;
7765         struct smb_filename *smb_fname_dst = NULL;
7766         char *fname_src = NULL;
7767         char *fname_dst = NULL;
7768         char *fname_src_mask = NULL;
7769         char *fname_src_dir = NULL;
7770         const char *p;
7771         int count=0;
7772         int error = ERRnoaccess;
7773         int tid2;
7774         int ofun;
7775         int flags;
7776         bool target_is_directory=False;
7777         bool source_has_wild = False;
7778         bool dest_has_wild = False;
7779         NTSTATUS status;
7780         uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7781                 ucf_flags_from_smb_request(req);
7782         uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7783                 ucf_flags_from_smb_request(req);
7784         TALLOC_CTX *ctx = talloc_tos();
7785
7786         START_PROFILE(SMBcopy);
7787
7788         if (req->wct < 3) {
7789                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7790                 goto out;
7791         }
7792
7793         tid2 = SVAL(req->vwv+0, 0);
7794         ofun = SVAL(req->vwv+1, 0);
7795         flags = SVAL(req->vwv+2, 0);
7796
7797         p = (const char *)req->buf;
7798         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7799                                        &status, &source_has_wild);
7800         if (!NT_STATUS_IS_OK(status)) {
7801                 reply_nterror(req, status);
7802                 goto out;
7803         }
7804         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7805                                        &status, &dest_has_wild);
7806         if (!NT_STATUS_IS_OK(status)) {
7807                 reply_nterror(req, status);
7808                 goto out;
7809         }
7810
7811         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7812
7813         if (tid2 != conn->cnum) {
7814                 /* can't currently handle inter share copies XXXX */
7815                 DEBUG(3,("Rejecting inter-share copy\n"));
7816                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7817                 goto out;
7818         }
7819
7820         status = filename_convert(ctx, conn,
7821                                   fname_src,
7822                                   ucf_flags_src,
7823                                   NULL,
7824                                   &source_has_wild,
7825                                   &smb_fname_src);
7826         if (!NT_STATUS_IS_OK(status)) {
7827                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7828                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7829                                         ERRSRV, ERRbadpath);
7830                         goto out;
7831                 }
7832                 reply_nterror(req, status);
7833                 goto out;
7834         }
7835
7836         status = filename_convert(ctx, conn,
7837                                   fname_dst,
7838                                   ucf_flags_dst,
7839                                   NULL,
7840                                   &dest_has_wild,
7841                                   &smb_fname_dst);
7842         if (!NT_STATUS_IS_OK(status)) {
7843                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7844                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7845                                         ERRSRV, ERRbadpath);
7846                         goto out;
7847                 }
7848                 reply_nterror(req, status);
7849                 goto out;
7850         }
7851
7852         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7853
7854         if ((flags&1) && target_is_directory) {
7855                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7856                 goto out;
7857         }
7858
7859         if ((flags&2) && !target_is_directory) {
7860                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7861                 goto out;
7862         }
7863
7864         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7865                 /* wants a tree copy! XXXX */
7866                 DEBUG(3,("Rejecting tree copy\n"));
7867                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868                 goto out;
7869         }
7870
7871         /* Split up the directory from the filename/mask. */
7872         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7873                                       &fname_src_dir, &fname_src_mask);
7874         if (!NT_STATUS_IS_OK(status)) {
7875                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7876                 goto out;
7877         }
7878
7879         /*
7880          * We should only check the mangled cache
7881          * here if unix_convert failed. This means
7882          * that the path in 'mask' doesn't exist
7883          * on the file system and so we need to look
7884          * for a possible mangle. This patch from
7885          * Tine Smukavec <valentin.smukavec@hermes.si>.
7886          */
7887         if (!VALID_STAT(smb_fname_src->st) &&
7888             mangle_is_mangled(fname_src_mask, conn->params)) {
7889                 char *new_mask = NULL;
7890                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7891                                             &new_mask, conn->params);
7892
7893                 /* Use demangled name if one was successfully found. */
7894                 if (new_mask) {
7895                         TALLOC_FREE(fname_src_mask);
7896                         fname_src_mask = new_mask;
7897                 }
7898         }
7899
7900         if (!source_has_wild) {
7901
7902                 /*
7903                  * Only one file needs to be copied. Append the mask back onto
7904                  * the directory.
7905                  */
7906                 TALLOC_FREE(smb_fname_src->base_name);
7907                 if (ISDOT(fname_src_dir)) {
7908                         /* Ensure we use canonical names on open. */
7909                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7910                                                         "%s",
7911                                                         fname_src_mask);
7912                 } else {
7913                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7914                                                         "%s/%s",
7915                                                         fname_src_dir,
7916                                                         fname_src_mask);
7917                 }
7918                 if (!smb_fname_src->base_name) {
7919                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7920                         goto out;
7921                 }
7922
7923                 if (dest_has_wild) {
7924                         char *fname_dst_mod = NULL;
7925                         if (!resolve_wildcards(smb_fname_dst,
7926                                                smb_fname_src->base_name,
7927                                                smb_fname_dst->base_name,
7928                                                &fname_dst_mod)) {
7929                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7930                                 goto out;
7931                         }
7932                         TALLOC_FREE(smb_fname_dst->base_name);
7933                         smb_fname_dst->base_name = fname_dst_mod;
7934                 }
7935
7936                 status = check_name(conn, smb_fname_src);
7937                 if (!NT_STATUS_IS_OK(status)) {
7938                         reply_nterror(req, status);
7939                         goto out;
7940                 }
7941
7942                 status = check_name(conn, smb_fname_dst);
7943                 if (!NT_STATUS_IS_OK(status)) {
7944                         reply_nterror(req, status);
7945                         goto out;
7946                 }
7947
7948                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7949                                    ofun, count, target_is_directory);
7950
7951                 if(!NT_STATUS_IS_OK(status)) {
7952                         reply_nterror(req, status);
7953                         goto out;
7954                 } else {
7955                         count++;
7956                 }
7957         } else {
7958                 struct smb_Dir *dir_hnd = NULL;
7959                 const char *dname = NULL;
7960                 char *talloced = NULL;
7961                 long offset = 0;
7962
7963                 /*
7964                  * There is a wildcard that requires us to actually read the
7965                  * src dir and copy each file matching the mask to the dst.
7966                  * Right now streams won't be copied, but this could
7967                  * presumably be added with a nested loop for reach dir entry.
7968                  */
7969                 SMB_ASSERT(!smb_fname_src->stream_name);
7970                 SMB_ASSERT(!smb_fname_dst->stream_name);
7971
7972                 smb_fname_src->stream_name = NULL;
7973                 smb_fname_dst->stream_name = NULL;
7974
7975                 if (strequal(fname_src_mask,"????????.???")) {
7976                         TALLOC_FREE(fname_src_mask);
7977                         fname_src_mask = talloc_strdup(ctx, "*");
7978                         if (!fname_src_mask) {
7979                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7980                                 goto out;
7981                         }
7982                 }
7983
7984                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7985                                         fname_src_dir,
7986                                         NULL,
7987                                         NULL,
7988                                         smb_fname_src->flags);
7989                 if (smb_fname_src_dir == NULL) {
7990                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7991                         goto out;
7992                 }
7993
7994                 status = check_name(conn, smb_fname_src_dir);
7995                 if (!NT_STATUS_IS_OK(status)) {
7996                         reply_nterror(req, status);
7997                         goto out;
7998                 }
7999
8000                 dir_hnd = OpenDir(ctx,
8001                                 conn,
8002                                 smb_fname_src_dir,
8003                                 fname_src_mask,
8004                                 0);
8005                 if (dir_hnd == NULL) {
8006                         status = map_nt_error_from_unix(errno);
8007                         reply_nterror(req, status);
8008                         goto out;
8009                 }
8010
8011                 error = ERRbadfile;
8012
8013                 /* Iterate over the src dir copying each entry to the dst. */
8014                 while ((dname = ReadDirName(dir_hnd, &offset,
8015                                             &smb_fname_src->st, &talloced))) {
8016                         char *destname = NULL;
8017
8018                         if (ISDOT(dname) || ISDOTDOT(dname)) {
8019                                 TALLOC_FREE(talloced);
8020                                 continue;
8021                         }
8022
8023                         if (!is_visible_file(conn, fname_src_dir, dname,
8024                                              &smb_fname_src->st, false)) {
8025                                 TALLOC_FREE(talloced);
8026                                 continue;
8027                         }
8028
8029                         if(!mask_match(dname, fname_src_mask,
8030                                        conn->case_sensitive)) {
8031                                 TALLOC_FREE(talloced);
8032                                 continue;
8033                         }
8034
8035                         error = ERRnoaccess;
8036
8037                         /* Get the src smb_fname struct setup. */
8038                         TALLOC_FREE(smb_fname_src->base_name);
8039                         if (ISDOT(fname_src_dir)) {
8040                                 /* Ensure we use canonical names on open. */
8041                                 smb_fname_src->base_name =
8042                                         talloc_asprintf(smb_fname_src, "%s",
8043                                                 dname);
8044                         } else {
8045                                 smb_fname_src->base_name =
8046                                         talloc_asprintf(smb_fname_src, "%s/%s",
8047                                                 fname_src_dir, dname);
8048                         }
8049
8050                         if (!smb_fname_src->base_name) {
8051                                 TALLOC_FREE(dir_hnd);
8052                                 TALLOC_FREE(talloced);
8053                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8054                                 goto out;
8055                         }
8056
8057                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8058                                                smb_fname_dst->base_name,
8059                                                &destname)) {
8060                                 TALLOC_FREE(talloced);
8061                                 continue;
8062                         }
8063                         if (!destname) {
8064                                 TALLOC_FREE(dir_hnd);
8065                                 TALLOC_FREE(talloced);
8066                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8067                                 goto out;
8068                         }
8069
8070                         TALLOC_FREE(smb_fname_dst->base_name);
8071                         smb_fname_dst->base_name = destname;
8072
8073                         status = check_name(conn, smb_fname_src);
8074                         if (!NT_STATUS_IS_OK(status)) {
8075                                 TALLOC_FREE(dir_hnd);
8076                                 TALLOC_FREE(talloced);
8077                                 reply_nterror(req, status);
8078                                 goto out;
8079                         }
8080
8081                         status = check_name(conn, smb_fname_dst);
8082                         if (!NT_STATUS_IS_OK(status)) {
8083                                 TALLOC_FREE(dir_hnd);
8084                                 TALLOC_FREE(talloced);
8085                                 reply_nterror(req, status);
8086                                 goto out;
8087                         }
8088
8089                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8090                                 smb_fname_src->base_name,
8091                                 smb_fname_dst->base_name));
8092
8093                         status = copy_file(ctx, conn, smb_fname_src,
8094                                            smb_fname_dst, ofun, count,
8095                                            target_is_directory);
8096                         if (NT_STATUS_IS_OK(status)) {
8097                                 count++;
8098                         }
8099
8100                         TALLOC_FREE(talloced);
8101                 }
8102                 TALLOC_FREE(dir_hnd);
8103         }
8104
8105         if (count == 0) {
8106                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8107                 goto out;
8108         }
8109
8110         reply_outbuf(req, 1, 0);
8111         SSVAL(req->outbuf,smb_vwv0,count);
8112  out:
8113         TALLOC_FREE(smb_fname_src);
8114         TALLOC_FREE(smb_fname_src_dir);
8115         TALLOC_FREE(smb_fname_dst);
8116         TALLOC_FREE(fname_src);
8117         TALLOC_FREE(fname_dst);
8118         TALLOC_FREE(fname_src_mask);
8119         TALLOC_FREE(fname_src_dir);
8120
8121         END_PROFILE(SMBcopy);
8122         return;
8123 }
8124
8125 #undef DBGC_CLASS
8126 #define DBGC_CLASS DBGC_LOCKING
8127
8128 /****************************************************************************
8129  Get a lock pid, dealing with large count requests.
8130 ****************************************************************************/
8131
8132 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8133                     bool large_file_format)
8134 {
8135         if(!large_file_format)
8136                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8137         else
8138                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8139 }
8140
8141 /****************************************************************************
8142  Get a lock count, dealing with large count requests.
8143 ****************************************************************************/
8144
8145 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8146                         bool large_file_format)
8147 {
8148         uint64_t count = 0;
8149
8150         if(!large_file_format) {
8151                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8152         } else {
8153                 /*
8154                  * No BVAL, this is reversed!
8155                  */
8156                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8157                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8158         }
8159
8160         return count;
8161 }
8162
8163 /****************************************************************************
8164  Get a lock offset, dealing with large offset requests.
8165 ****************************************************************************/
8166
8167 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8168                          bool large_file_format)
8169 {
8170         uint64_t offset = 0;
8171
8172         if(!large_file_format) {
8173                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8174         } else {
8175                 /*
8176                  * No BVAL, this is reversed!
8177                  */
8178                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8179                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8180         }
8181
8182         return offset;
8183 }
8184
8185 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8186                            files_struct *fsp,
8187                            uint16_t num_ulocks,
8188                            struct smbd_lock_element *ulocks,
8189                            enum brl_flavour lock_flav)
8190 {
8191         struct share_mode_lock *lck;
8192         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8193         uint16_t i;
8194
8195         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8196
8197         for(i = 0; i < num_ulocks; i++) {
8198                 struct smbd_lock_element *e = &ulocks[i];
8199
8200                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8201                           "pid %"PRIu64", file %s\n",
8202                           e->offset,
8203                           e->count,
8204                           e->smblctx,
8205                           fsp_str_dbg(fsp));
8206
8207                 if (e->brltype != UNLOCK_LOCK) {
8208                         /* this can only happen with SMB2 */
8209                         status = NT_STATUS_INVALID_PARAMETER;
8210                         goto done;
8211                 }
8212
8213                 status = do_unlock(
8214                         fsp,
8215                         e->smblctx,
8216                         e->count,
8217                         e->offset,
8218                         lock_flav);
8219
8220                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8221                            nt_errstr(status)));
8222
8223                 if (!NT_STATUS_IS_OK(status)) {
8224                         goto done;
8225                 }
8226         }
8227
8228         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8229                   num_ulocks));
8230
8231 done:
8232         if (NT_STATUS_IS_OK(status) && (lck != NULL)) {
8233                 lck->data->modified = true;
8234         }
8235
8236         TALLOC_FREE(lck);
8237         return status;
8238 }
8239
8240 /****************************************************************************
8241  Reply to a lockingX request.
8242 ****************************************************************************/
8243
8244 static void reply_lockingx_done(struct tevent_req *subreq);
8245
8246 void reply_lockingX(struct smb_request *req)
8247 {
8248         connection_struct *conn = req->conn;
8249         files_struct *fsp;
8250         unsigned char locktype;
8251         enum brl_type brltype;
8252         unsigned char oplocklevel;
8253         uint16_t num_ulocks;
8254         uint16_t num_locks;
8255         int32_t lock_timeout;
8256         uint16_t i;
8257         const uint8_t *data;
8258         bool large_file_format;
8259         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8260         struct smbd_lock_element *locks = NULL;
8261         struct tevent_req *subreq = NULL;
8262
8263         START_PROFILE(SMBlockingX);
8264
8265         if (req->wct < 8) {
8266                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8267                 END_PROFILE(SMBlockingX);
8268                 return;
8269         }
8270
8271         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8272         locktype = CVAL(req->vwv+3, 0);
8273         oplocklevel = CVAL(req->vwv+3, 1);
8274         num_ulocks = SVAL(req->vwv+6, 0);
8275         num_locks = SVAL(req->vwv+7, 0);
8276         lock_timeout = IVAL(req->vwv+4, 0);
8277         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8278
8279         if (!check_fsp(conn, req, fsp)) {
8280                 END_PROFILE(SMBlockingX);
8281                 return;
8282         }
8283
8284         data = req->buf;
8285
8286         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8287                 /* we don't support these - and CANCEL_LOCK makes w2k
8288                    and XP reboot so I don't really want to be
8289                    compatible! (tridge) */
8290                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8291                 END_PROFILE(SMBlockingX);
8292                 return;
8293         }
8294
8295         /* Check if this is an oplock break on a file
8296            we have granted an oplock on.
8297         */
8298         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8299                 /* Client can insist on breaking to none. */
8300                 bool break_to_none = (oplocklevel == 0);
8301                 bool result;
8302
8303                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8304                          "for %s\n", (unsigned int)oplocklevel,
8305                          fsp_fnum_dbg(fsp)));
8306
8307                 /*
8308                  * Make sure we have granted an exclusive or batch oplock on
8309                  * this file.
8310                  */
8311
8312                 if (fsp->oplock_type == 0) {
8313
8314                         /* The Samba4 nbench simulator doesn't understand
8315                            the difference between break to level2 and break
8316                            to none from level2 - it sends oplock break
8317                            replies in both cases. Don't keep logging an error
8318                            message here - just ignore it. JRA. */
8319
8320                         DEBUG(5,("reply_lockingX: Error : oplock break from "
8321                                  "client for %s (oplock=%d) and no "
8322                                  "oplock granted on this file (%s).\n",
8323                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
8324                                  fsp_str_dbg(fsp)));
8325
8326                         /* if this is a pure oplock break request then don't
8327                          * send a reply */
8328                         if (num_locks == 0 && num_ulocks == 0) {
8329                                 END_PROFILE(SMBlockingX);
8330                                 return;
8331                         }
8332
8333                         END_PROFILE(SMBlockingX);
8334                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8335                         return;
8336                 }
8337
8338                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8339                     (break_to_none)) {
8340                         result = remove_oplock(fsp);
8341                 } else {
8342                         result = downgrade_oplock(fsp);
8343                 }
8344
8345                 if (!result) {
8346                         DEBUG(0, ("reply_lockingX: error in removing "
8347                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
8348                         /* Hmmm. Is this panic justified? */
8349                         smb_panic("internal tdb error");
8350                 }
8351
8352                 /* if this is a pure oplock break request then don't send a
8353                  * reply */
8354                 if (num_locks == 0 && num_ulocks == 0) {
8355                         /* Sanity check - ensure a pure oplock break is not a
8356                            chained request. */
8357                         if (CVAL(req->vwv+0, 0) != 0xff) {
8358                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8359                                          "break is a chained %d request !\n",
8360                                          (unsigned int)CVAL(req->vwv+0, 0)));
8361                         }
8362                         END_PROFILE(SMBlockingX);
8363                         return;
8364                 }
8365         }
8366
8367         if (req->buflen <
8368             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8369                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8370                 END_PROFILE(SMBlockingX);
8371                 return;
8372         }
8373
8374         if (num_ulocks != 0) {
8375                 struct smbd_lock_element *ulocks = NULL;
8376                 bool ok;
8377
8378                 ulocks = talloc_array(
8379                         req, struct smbd_lock_element, num_ulocks);
8380                 if (ulocks == NULL) {
8381                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8382                         END_PROFILE(SMBlockingX);
8383                         return;
8384                 }
8385
8386                 /*
8387                  * Data now points at the beginning of the list of
8388                  * smb_unlkrng structs
8389                  */
8390                 for (i = 0; i < num_ulocks; i++) {
8391                         ulocks[i].smblctx = get_lock_pid(
8392                                 data, i, large_file_format);
8393                         ulocks[i].count = get_lock_count(
8394                                 data, i, large_file_format);
8395                         ulocks[i].offset = get_lock_offset(
8396                                 data, i, large_file_format);
8397                         ulocks[i].brltype = UNLOCK_LOCK;
8398                 }
8399
8400                 /*
8401                  * Unlock cancels pending locks
8402                  */
8403
8404                 ok = smbd_smb1_brl_finish_by_lock(
8405                         fsp,
8406                         large_file_format,
8407                         WINDOWS_LOCK,
8408                         ulocks[0],
8409                         NT_STATUS_OK);
8410                 if (ok) {
8411                         reply_outbuf(req, 2, 0);
8412                         SSVAL(req->outbuf, smb_vwv0, 0xff);
8413                         SSVAL(req->outbuf, smb_vwv1, 0);
8414                         END_PROFILE(SMBlockingX);
8415                         return;
8416                 }
8417
8418                 status = smbd_do_unlocking(
8419                         req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8420                 TALLOC_FREE(ulocks);
8421                 if (!NT_STATUS_IS_OK(status)) {
8422                         END_PROFILE(SMBlockingX);
8423                         reply_nterror(req, status);
8424                         return;
8425                 }
8426         }
8427
8428         /* Now do any requested locks */
8429         data += ((large_file_format ? 20 : 10)*num_ulocks);
8430
8431         /* Data now points at the beginning of the list
8432            of smb_lkrng structs */
8433
8434         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8435                 brltype = READ_LOCK;
8436         } else {
8437                 brltype = WRITE_LOCK;
8438         }
8439
8440         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8441         if (locks == NULL) {
8442                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8443                 END_PROFILE(SMBlockingX);
8444                 return;
8445         }
8446
8447         for (i = 0; i < num_locks; i++) {
8448                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8449                 locks[i].count = get_lock_count(data, i, large_file_format);
8450                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8451                 locks[i].brltype = brltype;
8452         }
8453
8454         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8455
8456                 bool ok;
8457
8458                 if (num_locks == 0) {
8459                         /* See smbtorture3 lock11 test */
8460                         reply_outbuf(req, 2, 0);
8461                         /* andx chain ends */
8462                         SSVAL(req->outbuf, smb_vwv0, 0xff);
8463                         SSVAL(req->outbuf, smb_vwv1, 0);
8464                         END_PROFILE(SMBlockingX);
8465                         return;
8466                 }
8467
8468                 ok = smbd_smb1_brl_finish_by_lock(
8469                         fsp,
8470                         large_file_format,
8471                         WINDOWS_LOCK,
8472                         locks[0], /* Windows only cancels the first lock */
8473                         NT_STATUS_FILE_LOCK_CONFLICT);
8474
8475                 if (!ok) {
8476                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8477                         END_PROFILE(SMBlockingX);
8478                         return;
8479                 }
8480
8481                 reply_outbuf(req, 2, 0);
8482                 SSVAL(req->outbuf, smb_vwv0, 0xff);
8483                 SSVAL(req->outbuf, smb_vwv1, 0);
8484                 END_PROFILE(SMBlockingX);
8485                 return;
8486         }
8487
8488         subreq = smbd_smb1_do_locks_send(
8489                 fsp,
8490                 req->sconn->ev_ctx,
8491                 &req,
8492                 fsp,
8493                 lock_timeout,
8494                 large_file_format,
8495                 WINDOWS_LOCK,
8496                 num_locks,
8497                 locks);
8498         if (subreq == NULL) {
8499                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8500                 END_PROFILE(SMBlockingX);
8501                 return;
8502         }
8503         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8504         END_PROFILE(SMBlockingX);
8505 }
8506
8507 static void reply_lockingx_done(struct tevent_req *subreq)
8508 {
8509         struct smb_request *req = NULL;
8510         NTSTATUS status;
8511         bool ok;
8512
8513         START_PROFILE(SMBlockingX);
8514
8515         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8516         SMB_ASSERT(ok);
8517
8518         status = smbd_smb1_do_locks_recv(subreq);
8519         TALLOC_FREE(subreq);
8520
8521         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8522
8523         if (NT_STATUS_IS_OK(status)) {
8524                 reply_outbuf(req, 2, 0);
8525                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8526                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8527         } else {
8528                 reply_nterror(req, status);
8529         }
8530
8531         ok = srv_send_smb(req->xconn,
8532                           (char *)req->outbuf,
8533                           true,
8534                           req->seqnum+1,
8535                           IS_CONN_ENCRYPTED(req->conn),
8536                           NULL);
8537         if (!ok) {
8538                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8539         }
8540         TALLOC_FREE(req);
8541         END_PROFILE(SMBlockingX);
8542 }
8543
8544 #undef DBGC_CLASS
8545 #define DBGC_CLASS DBGC_ALL
8546
8547 /****************************************************************************
8548  Reply to a SMBreadbmpx (read block multiplex) request.
8549  Always reply with an error, if someone has a platform really needs this,
8550  please contact vl@samba.org
8551 ****************************************************************************/
8552
8553 void reply_readbmpx(struct smb_request *req)
8554 {
8555         START_PROFILE(SMBreadBmpx);
8556         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8557         END_PROFILE(SMBreadBmpx);
8558         return;
8559 }
8560
8561 /****************************************************************************
8562  Reply to a SMBreadbs (read block multiplex secondary) request.
8563  Always reply with an error, if someone has a platform really needs this,
8564  please contact vl@samba.org
8565 ****************************************************************************/
8566
8567 void reply_readbs(struct smb_request *req)
8568 {
8569         START_PROFILE(SMBreadBs);
8570         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8571         END_PROFILE(SMBreadBs);
8572         return;
8573 }
8574
8575 /****************************************************************************
8576  Reply to a SMBsetattrE.
8577 ****************************************************************************/
8578
8579 void reply_setattrE(struct smb_request *req)
8580 {
8581         connection_struct *conn = req->conn;
8582         struct smb_file_time ft;
8583         files_struct *fsp;
8584         NTSTATUS status;
8585
8586         START_PROFILE(SMBsetattrE);
8587         ZERO_STRUCT(ft);
8588
8589         if (req->wct < 7) {
8590                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8591                 goto out;
8592         }
8593
8594         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8595
8596         if(!fsp || (fsp->conn != conn)) {
8597                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8598                 goto out;
8599         }
8600
8601         /*
8602          * Convert the DOS times into unix times.
8603          */
8604
8605         ft.atime = convert_time_t_to_timespec(
8606             srv_make_unix_date2(req->vwv+3));
8607         ft.mtime = convert_time_t_to_timespec(
8608             srv_make_unix_date2(req->vwv+5));
8609         ft.create_time = convert_time_t_to_timespec(
8610             srv_make_unix_date2(req->vwv+1));
8611
8612         reply_outbuf(req, 0, 0);
8613
8614         /* 
8615          * Patch from Ray Frush <frush@engr.colostate.edu>
8616          * Sometimes times are sent as zero - ignore them.
8617          */
8618
8619         /* Ensure we have a valid stat struct for the source. */
8620         status = vfs_stat_fsp(fsp);
8621         if (!NT_STATUS_IS_OK(status)) {
8622                 reply_nterror(req, status);
8623                 goto out;
8624         }
8625
8626         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8627                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8628                 goto out;
8629         }
8630
8631         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8632         if (!NT_STATUS_IS_OK(status)) {
8633                 reply_nterror(req, status);
8634                 goto out;
8635         }
8636
8637         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8638                " createtime=%u\n",
8639                 fsp_fnum_dbg(fsp),
8640                 (unsigned int)ft.atime.tv_sec,
8641                 (unsigned int)ft.mtime.tv_sec,
8642                 (unsigned int)ft.create_time.tv_sec
8643                 ));
8644  out:
8645         END_PROFILE(SMBsetattrE);
8646         return;
8647 }
8648
8649
8650 /* Back from the dead for OS/2..... JRA. */
8651
8652 /****************************************************************************
8653  Reply to a SMBwritebmpx (write block multiplex primary) request.
8654  Always reply with an error, if someone has a platform really needs this,
8655  please contact vl@samba.org
8656 ****************************************************************************/
8657
8658 void reply_writebmpx(struct smb_request *req)
8659 {
8660         START_PROFILE(SMBwriteBmpx);
8661         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8662         END_PROFILE(SMBwriteBmpx);
8663         return;
8664 }
8665
8666 /****************************************************************************
8667  Reply to a SMBwritebs (write block multiplex secondary) request.
8668  Always reply with an error, if someone has a platform really needs this,
8669  please contact vl@samba.org
8670 ****************************************************************************/
8671
8672 void reply_writebs(struct smb_request *req)
8673 {
8674         START_PROFILE(SMBwriteBs);
8675         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8676         END_PROFILE(SMBwriteBs);
8677         return;
8678 }
8679
8680 /****************************************************************************
8681  Reply to a SMBgetattrE.
8682 ****************************************************************************/
8683
8684 void reply_getattrE(struct smb_request *req)
8685 {
8686         connection_struct *conn = req->conn;
8687         int mode;
8688         files_struct *fsp;
8689         struct timespec create_ts;
8690
8691         START_PROFILE(SMBgetattrE);
8692
8693         if (req->wct < 1) {
8694                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8695                 END_PROFILE(SMBgetattrE);
8696                 return;
8697         }
8698
8699         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8700
8701         if(!fsp || (fsp->conn != conn)) {
8702                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8703                 END_PROFILE(SMBgetattrE);
8704                 return;
8705         }
8706
8707         /* Do an fstat on this file */
8708         if(fsp_stat(fsp)) {
8709                 reply_nterror(req, map_nt_error_from_unix(errno));
8710                 END_PROFILE(SMBgetattrE);
8711                 return;
8712         }
8713
8714         mode = dos_mode(conn, fsp->fsp_name);
8715
8716         /*
8717          * Convert the times into dos times. Set create
8718          * date to be last modify date as UNIX doesn't save
8719          * this.
8720          */
8721
8722         reply_outbuf(req, 11, 0);
8723
8724         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8725         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8726         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8727                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8728         /* Should we check pending modtime here ? JRA */
8729         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8730                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8731
8732         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8733                 SIVAL(req->outbuf, smb_vwv6, 0);
8734                 SIVAL(req->outbuf, smb_vwv8, 0);
8735         } else {
8736                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8737                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8738                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8739         }
8740         SSVAL(req->outbuf,smb_vwv10, mode);
8741
8742         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8743
8744         END_PROFILE(SMBgetattrE);
8745         return;
8746 }