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