s3:smbd: Fix converity warning with _smb_setlen_large()
[metze/samba/wip.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         /* Make a copy of the dst smb_fname structs */
6647
6648         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6649         if (smb_fname_dst == NULL) {
6650                 status = NT_STATUS_NO_MEMORY;
6651                 goto out;
6652         }
6653
6654         /*
6655          * Check for special case with case preserving and not
6656          * case sensitive. If the new last component differs from the original
6657          * last component only by case, then we should allow
6658          * the rename (user is trying to change the case of the
6659          * filename).
6660          */
6661         if (!conn->case_sensitive && conn->case_preserve &&
6662             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6663             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6664                 char *fname_dst_parent = NULL;
6665                 const char *fname_dst_lcomp = NULL;
6666                 char *orig_lcomp_path = NULL;
6667                 char *orig_lcomp_stream = NULL;
6668                 bool ok = true;
6669
6670                 /*
6671                  * Split off the last component of the processed
6672                  * destination name. We will compare this to
6673                  * the split components of smb_fname_dst->original_lcomp.
6674                  */
6675                 if (!parent_dirname(ctx,
6676                                 smb_fname_dst->base_name,
6677                                 &fname_dst_parent,
6678                                 &fname_dst_lcomp)) {
6679                         status = NT_STATUS_NO_MEMORY;
6680                         goto out;
6681                 }
6682
6683                 /*
6684                  * The original_lcomp component contains
6685                  * the last_component of the path + stream
6686                  * name (if a stream exists).
6687                  *
6688                  * Split off the stream name so we
6689                  * can check them separately.
6690                  */
6691
6692                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6693                         /* POSIX - no stream component. */
6694                         orig_lcomp_path = talloc_strdup(ctx,
6695                                                 smb_fname_dst->original_lcomp);
6696                         if (orig_lcomp_path == NULL) {
6697                                 ok = false;
6698                         }
6699                 } else {
6700                         ok = split_stream_filename(ctx,
6701                                         smb_fname_dst->original_lcomp,
6702                                         &orig_lcomp_path,
6703                                         &orig_lcomp_stream);
6704                 }
6705
6706                 if (!ok) {
6707                         TALLOC_FREE(fname_dst_parent);
6708                         status = NT_STATUS_NO_MEMORY;
6709                         goto out;
6710                 }
6711
6712                 /* If the base names only differ by case, use original. */
6713                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6714                         char *tmp;
6715                         /*
6716                          * Replace the modified last component with the
6717                          * original.
6718                          */
6719                         if (!ISDOT(fname_dst_parent)) {
6720                                 tmp = talloc_asprintf(smb_fname_dst,
6721                                         "%s/%s",
6722                                         fname_dst_parent,
6723                                         orig_lcomp_path);
6724                         } else {
6725                                 tmp = talloc_strdup(smb_fname_dst,
6726                                         orig_lcomp_path);
6727                         }
6728                         if (tmp == NULL) {
6729                                 status = NT_STATUS_NO_MEMORY;
6730                                 TALLOC_FREE(fname_dst_parent);
6731                                 TALLOC_FREE(orig_lcomp_path);
6732                                 TALLOC_FREE(orig_lcomp_stream);
6733                                 goto out;
6734                         }
6735                         TALLOC_FREE(smb_fname_dst->base_name);
6736                         smb_fname_dst->base_name = tmp;
6737                 }
6738
6739                 /* If the stream_names only differ by case, use original. */
6740                 if(!strcsequal(smb_fname_dst->stream_name,
6741                                orig_lcomp_stream)) {
6742                         /* Use the original stream. */
6743                         char *tmp = talloc_strdup(smb_fname_dst,
6744                                             orig_lcomp_stream);
6745                         if (tmp == NULL) {
6746                                 status = NT_STATUS_NO_MEMORY;
6747                                 TALLOC_FREE(fname_dst_parent);
6748                                 TALLOC_FREE(orig_lcomp_path);
6749                                 TALLOC_FREE(orig_lcomp_stream);
6750                                 goto out;
6751                         }
6752                         TALLOC_FREE(smb_fname_dst->stream_name);
6753                         smb_fname_dst->stream_name = tmp;
6754                 }
6755                 TALLOC_FREE(fname_dst_parent);
6756                 TALLOC_FREE(orig_lcomp_path);
6757                 TALLOC_FREE(orig_lcomp_stream);
6758         }
6759
6760         /*
6761          * If the src and dest names are identical - including case,
6762          * don't do the rename, just return success.
6763          */
6764
6765         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6766             strcsequal(fsp->fsp_name->stream_name,
6767                        smb_fname_dst->stream_name)) {
6768                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6769                           "- returning success\n",
6770                           smb_fname_str_dbg(smb_fname_dst)));
6771                 status = NT_STATUS_OK;
6772                 goto out;
6773         }
6774
6775         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6776         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6777
6778         /* Return the correct error code if both names aren't streams. */
6779         if (!old_is_stream && new_is_stream) {
6780                 status = NT_STATUS_OBJECT_NAME_INVALID;
6781                 goto out;
6782         }
6783
6784         if (old_is_stream && !new_is_stream) {
6785                 status = NT_STATUS_INVALID_PARAMETER;
6786                 goto out;
6787         }
6788
6789         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6790
6791         if(!replace_if_exists && dst_exists) {
6792                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6793                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6794                           smb_fname_str_dbg(smb_fname_dst)));
6795                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6796                 goto out;
6797         }
6798
6799         if (dst_exists) {
6800                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6801                     &smb_fname_dst->st);
6802                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6803                                                            fileid);
6804                 /* The file can be open when renaming a stream */
6805                 if (dst_fsp && !new_is_stream) {
6806                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6807                         status = NT_STATUS_ACCESS_DENIED;
6808                         goto out;
6809                 }
6810         }
6811
6812         /* Ensure we have a valid stat struct for the source. */
6813         status = vfs_stat_fsp(fsp);
6814         if (!NT_STATUS_IS_OK(status)) {
6815                 goto out;
6816         }
6817
6818         status = can_rename(conn, fsp, attrs);
6819
6820         if (!NT_STATUS_IS_OK(status)) {
6821                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6822                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6823                           smb_fname_str_dbg(smb_fname_dst)));
6824                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6825                         status = NT_STATUS_ACCESS_DENIED;
6826                 goto out;
6827         }
6828
6829         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6830                 status = NT_STATUS_ACCESS_DENIED;
6831                 goto out;
6832         }
6833
6834         /* Do we have rights to move into the destination ? */
6835         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6836                 /* We're moving a directory. */
6837                 access_mask = SEC_DIR_ADD_SUBDIR;
6838         }
6839         status = check_parent_access(conn,
6840                                 smb_fname_dst,
6841                                 access_mask);
6842         if (!NT_STATUS_IS_OK(status)) {
6843                 DBG_INFO("check_parent_access on "
6844                         "dst %s returned %s\n",
6845                         smb_fname_str_dbg(smb_fname_dst),
6846                         nt_errstr(status));
6847                 goto out;
6848         }
6849
6850         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6851
6852         /*
6853          * We have the file open ourselves, so not being able to get the
6854          * corresponding share mode lock is a fatal error.
6855          */
6856
6857         SMB_ASSERT(lck != NULL);
6858
6859         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6860                 uint32_t create_options = fsp->fh->private_options;
6861
6862                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6863                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6864                           smb_fname_str_dbg(smb_fname_dst)));
6865
6866                 if (!fsp->is_directory &&
6867                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6868                     (lp_map_archive(SNUM(conn)) ||
6869                     lp_store_dos_attributes(SNUM(conn)))) {
6870                         /* We must set the archive bit on the newly
6871                            renamed file. */
6872                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6873                                 uint32_t old_dosmode = dos_mode(conn,
6874                                                         smb_fname_dst);
6875                                 file_set_dosmode(conn,
6876                                         smb_fname_dst,
6877                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6878                                         NULL,
6879                                         true);
6880                         }
6881                 }
6882
6883                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6884                               smb_fname_dst);
6885
6886                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6887                                   smb_fname_dst);
6888
6889                 /*
6890                  * A rename acts as a new file create w.r.t. allowing an initial delete
6891                  * on close, probably because in Windows there is a new handle to the
6892                  * new file. If initial delete on close was requested but not
6893                  * originally set, we need to set it here. This is probably not 100% correct,
6894                  * but will work for the CIFSFS client which in non-posix mode
6895                  * depends on these semantics. JRA.
6896                  */
6897
6898                 if (create_options & FILE_DELETE_ON_CLOSE) {
6899                         status = can_set_delete_on_close(fsp, 0);
6900
6901                         if (NT_STATUS_IS_OK(status)) {
6902                                 /* Note that here we set the *inital* delete on close flag,
6903                                  * not the regular one. The magic gets handled in close. */
6904                                 fsp->initial_delete_on_close = True;
6905                         }
6906                 }
6907                 TALLOC_FREE(lck);
6908                 status = NT_STATUS_OK;
6909                 goto out;
6910         }
6911
6912         TALLOC_FREE(lck);
6913
6914         if (errno == ENOTDIR || errno == EISDIR) {
6915                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6916         } else {
6917                 status = map_nt_error_from_unix(errno);
6918         }
6919
6920         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6921                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6922                   smb_fname_str_dbg(smb_fname_dst)));
6923
6924  out:
6925         TALLOC_FREE(smb_fname_dst);
6926
6927         return status;
6928 }
6929
6930 /****************************************************************************
6931  The guts of the rename command, split out so it may be called by the NT SMB
6932  code.
6933 ****************************************************************************/
6934
6935 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6936                         connection_struct *conn,
6937                         struct smb_request *req,
6938                         struct smb_filename *smb_fname_src,
6939                         struct smb_filename *smb_fname_dst,
6940                         uint32_t attrs,
6941                         bool replace_if_exists,
6942                         bool src_has_wild,
6943                         bool dest_has_wild,
6944                         uint32_t access_mask)
6945 {
6946         char *fname_src_dir = NULL;
6947         struct smb_filename *smb_fname_src_dir = NULL;
6948         char *fname_src_mask = NULL;
6949         int count=0;
6950         NTSTATUS status = NT_STATUS_OK;
6951         struct smb_Dir *dir_hnd = NULL;
6952         const char *dname = NULL;
6953         char *talloced = NULL;
6954         long offset = 0;
6955         int create_options = 0;
6956         bool posix_pathnames = (req != NULL && req->posix_pathnames);
6957         int rc;
6958
6959         /*
6960          * Split the old name into directory and last component
6961          * strings. Note that unix_convert may have stripped off a
6962          * leading ./ from both name and newname if the rename is
6963          * at the root of the share. We need to make sure either both
6964          * name and newname contain a / character or neither of them do
6965          * as this is checked in resolve_wildcards().
6966          */
6967
6968         /* Split up the directory from the filename/mask. */
6969         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6970                                       &fname_src_dir, &fname_src_mask);
6971         if (!NT_STATUS_IS_OK(status)) {
6972                 status = NT_STATUS_NO_MEMORY;
6973                 goto out;
6974         }
6975
6976         /*
6977          * We should only check the mangled cache
6978          * here if unix_convert failed. This means
6979          * that the path in 'mask' doesn't exist
6980          * on the file system and so we need to look
6981          * for a possible mangle. This patch from
6982          * Tine Smukavec <valentin.smukavec@hermes.si>.
6983          */
6984
6985         if (!VALID_STAT(smb_fname_src->st) &&
6986             mangle_is_mangled(fname_src_mask, conn->params)) {
6987                 char *new_mask = NULL;
6988                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6989                                             conn->params);
6990                 if (new_mask) {
6991                         TALLOC_FREE(fname_src_mask);
6992                         fname_src_mask = new_mask;
6993                 }
6994         }
6995
6996         if (!src_has_wild) {
6997                 files_struct *fsp;
6998
6999                 /*
7000                  * Only one file needs to be renamed. Append the mask back
7001                  * onto the directory.
7002                  */
7003                 TALLOC_FREE(smb_fname_src->base_name);
7004                 if (ISDOT(fname_src_dir)) {
7005                         /* Ensure we use canonical names on open. */
7006                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7007                                                         "%s",
7008                                                         fname_src_mask);
7009                 } else {
7010                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7011                                                         "%s/%s",
7012                                                         fname_src_dir,
7013                                                         fname_src_mask);
7014                 }
7015                 if (!smb_fname_src->base_name) {
7016                         status = NT_STATUS_NO_MEMORY;
7017                         goto out;
7018                 }
7019
7020                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7021                           "case_preserve = %d, short case preserve = %d, "
7022                           "directory = %s, newname = %s, "
7023                           "last_component_dest = %s\n",
7024                           conn->case_sensitive, conn->case_preserve,
7025                           conn->short_case_preserve,
7026                           smb_fname_str_dbg(smb_fname_src),
7027                           smb_fname_str_dbg(smb_fname_dst),
7028                           smb_fname_dst->original_lcomp));
7029
7030                 /* The dest name still may have wildcards. */
7031                 if (dest_has_wild) {
7032                         char *fname_dst_mod = NULL;
7033                         if (!resolve_wildcards(smb_fname_dst,
7034                                                smb_fname_src->base_name,
7035                                                smb_fname_dst->base_name,
7036                                                &fname_dst_mod)) {
7037                                 DEBUG(6, ("rename_internals: resolve_wildcards "
7038                                           "%s %s failed\n",
7039                                           smb_fname_src->base_name,
7040                                           smb_fname_dst->base_name));
7041                                 status = NT_STATUS_NO_MEMORY;
7042                                 goto out;
7043                         }
7044                         TALLOC_FREE(smb_fname_dst->base_name);
7045                         smb_fname_dst->base_name = fname_dst_mod;
7046                 }
7047
7048                 ZERO_STRUCT(smb_fname_src->st);
7049                 if (posix_pathnames) {
7050                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7051                 } else {
7052                         rc = SMB_VFS_STAT(conn, smb_fname_src);
7053                 }
7054                 if (rc == -1) {
7055                         status = map_nt_error_from_unix_common(errno);
7056                         goto out;
7057                 }
7058
7059                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7060                         create_options |= FILE_DIRECTORY_FILE;
7061                 }
7062
7063                 status = SMB_VFS_CREATE_FILE(
7064                         conn,                           /* conn */
7065                         req,                            /* req */
7066                         0,                              /* root_dir_fid */
7067                         smb_fname_src,                  /* fname */
7068                         access_mask,                    /* access_mask */
7069                         (FILE_SHARE_READ |              /* share_access */
7070                             FILE_SHARE_WRITE),
7071                         FILE_OPEN,                      /* create_disposition*/
7072                         create_options,                 /* create_options */
7073                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7074                         0,                              /* oplock_request */
7075                         NULL,                           /* lease */
7076                         0,                              /* allocation_size */
7077                         0,                              /* private_flags */
7078                         NULL,                           /* sd */
7079                         NULL,                           /* ea_list */
7080                         &fsp,                           /* result */
7081                         NULL,                           /* pinfo */
7082                         NULL, NULL);                    /* create context */
7083
7084                 if (!NT_STATUS_IS_OK(status)) {
7085                         DEBUG(3, ("Could not open rename source %s: %s\n",
7086                                   smb_fname_str_dbg(smb_fname_src),
7087                                   nt_errstr(status)));
7088                         goto out;
7089                 }
7090
7091                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7092                                               attrs, replace_if_exists);
7093
7094                 close_file(req, fsp, NORMAL_CLOSE);
7095
7096                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7097                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7098                           smb_fname_str_dbg(smb_fname_dst)));
7099
7100                 goto out;
7101         }
7102
7103         /*
7104          * Wildcards - process each file that matches.
7105          */
7106         if (strequal(fname_src_mask, "????????.???")) {
7107                 TALLOC_FREE(fname_src_mask);
7108                 fname_src_mask = talloc_strdup(ctx, "*");
7109                 if (!fname_src_mask) {
7110                         status = NT_STATUS_NO_MEMORY;
7111                         goto out;
7112                 }
7113         }
7114
7115         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7116                                 fname_src_dir,
7117                                 NULL,
7118                                 NULL,
7119                                 smb_fname_src->flags);
7120         if (smb_fname_src_dir == NULL) {
7121                 status = NT_STATUS_NO_MEMORY;
7122                 goto out;
7123         }
7124
7125         status = check_name(conn, smb_fname_src_dir);
7126         if (!NT_STATUS_IS_OK(status)) {
7127                 goto out;
7128         }
7129
7130         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7131                           attrs);
7132         if (dir_hnd == NULL) {
7133                 status = map_nt_error_from_unix(errno);
7134                 goto out;
7135         }
7136
7137         status = NT_STATUS_NO_SUCH_FILE;
7138         /*
7139          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7140          * - gentest fix. JRA
7141          */
7142
7143         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7144                                     &talloced))) {
7145                 files_struct *fsp = NULL;
7146                 char *destname = NULL;
7147                 bool sysdir_entry = False;
7148
7149                 /* Quick check for "." and ".." */
7150                 if (ISDOT(dname) || ISDOTDOT(dname)) {
7151                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7152                                 sysdir_entry = True;
7153                         } else {
7154                                 TALLOC_FREE(talloced);
7155                                 continue;
7156                         }
7157                 }
7158
7159                 if (!is_visible_file(conn, fname_src_dir, dname,
7160                                      &smb_fname_src->st, false)) {
7161                         TALLOC_FREE(talloced);
7162                         continue;
7163                 }
7164
7165                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7166                         TALLOC_FREE(talloced);
7167                         continue;
7168                 }
7169
7170                 if (sysdir_entry) {
7171                         status = NT_STATUS_OBJECT_NAME_INVALID;
7172                         break;
7173                 }
7174
7175                 TALLOC_FREE(smb_fname_src->base_name);
7176                 if (ISDOT(fname_src_dir)) {
7177                         /* Ensure we use canonical names on open. */
7178                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7179                                                         "%s",
7180                                                         dname);
7181                 } else {
7182                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7183                                                         "%s/%s",
7184                                                         fname_src_dir,
7185                                                         dname);
7186                 }
7187                 if (!smb_fname_src->base_name) {
7188                         status = NT_STATUS_NO_MEMORY;
7189                         goto out;
7190                 }
7191
7192                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7193                                        smb_fname_dst->base_name,
7194                                        &destname)) {
7195                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
7196                                   smb_fname_src->base_name, destname));
7197                         TALLOC_FREE(talloced);
7198                         continue;
7199                 }
7200                 if (!destname) {
7201                         status = NT_STATUS_NO_MEMORY;
7202                         goto out;
7203                 }
7204
7205                 TALLOC_FREE(smb_fname_dst->base_name);
7206                 smb_fname_dst->base_name = destname;
7207
7208                 ZERO_STRUCT(smb_fname_src->st);
7209                 if (posix_pathnames) {
7210                         SMB_VFS_LSTAT(conn, smb_fname_src);
7211                 } else {
7212                         SMB_VFS_STAT(conn, smb_fname_src);
7213                 }
7214
7215                 create_options = 0;
7216
7217                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7218                         create_options |= FILE_DIRECTORY_FILE;
7219                 }
7220
7221                 status = SMB_VFS_CREATE_FILE(
7222                         conn,                           /* conn */
7223                         req,                            /* req */
7224                         0,                              /* root_dir_fid */
7225                         smb_fname_src,                  /* fname */
7226                         access_mask,                    /* access_mask */
7227                         (FILE_SHARE_READ |              /* share_access */
7228                             FILE_SHARE_WRITE),
7229                         FILE_OPEN,                      /* create_disposition*/
7230                         create_options,                 /* create_options */
7231                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7232                         0,                              /* oplock_request */
7233                         NULL,                           /* lease */
7234                         0,                              /* allocation_size */
7235                         0,                              /* private_flags */
7236                         NULL,                           /* sd */
7237                         NULL,                           /* ea_list */
7238                         &fsp,                           /* result */
7239                         NULL,                           /* pinfo */
7240                         NULL, NULL);                    /* create context */
7241
7242                 if (!NT_STATUS_IS_OK(status)) {
7243                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7244                                  "returned %s rename %s -> %s\n",
7245                                  nt_errstr(status),
7246                                  smb_fname_str_dbg(smb_fname_src),
7247                                  smb_fname_str_dbg(smb_fname_dst)));
7248                         break;
7249                 }
7250
7251                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7252                                                               dname);
7253                 if (!smb_fname_dst->original_lcomp) {
7254                         status = NT_STATUS_NO_MEMORY;
7255                         goto out;
7256                 }
7257
7258                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7259                                               attrs, replace_if_exists);
7260
7261                 close_file(req, fsp, NORMAL_CLOSE);
7262
7263                 if (!NT_STATUS_IS_OK(status)) {
7264                         DEBUG(3, ("rename_internals_fsp returned %s for "
7265                                   "rename %s -> %s\n", nt_errstr(status),
7266                                   smb_fname_str_dbg(smb_fname_src),
7267                                   smb_fname_str_dbg(smb_fname_dst)));
7268                         break;
7269                 }
7270
7271                 count++;
7272
7273                 DEBUG(3,("rename_internals: doing rename on %s -> "
7274                          "%s\n", smb_fname_str_dbg(smb_fname_src),
7275                          smb_fname_str_dbg(smb_fname_src)));
7276                 TALLOC_FREE(talloced);
7277         }
7278         TALLOC_FREE(dir_hnd);
7279
7280         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7281                 status = map_nt_error_from_unix(errno);
7282         }
7283
7284  out:
7285         TALLOC_FREE(talloced);
7286         TALLOC_FREE(smb_fname_src_dir);
7287         TALLOC_FREE(fname_src_dir);
7288         TALLOC_FREE(fname_src_mask);
7289         return status;
7290 }
7291
7292 /****************************************************************************
7293  Reply to a mv.
7294 ****************************************************************************/
7295
7296 void reply_mv(struct smb_request *req)
7297 {
7298         connection_struct *conn = req->conn;
7299         char *name = NULL;
7300         char *newname = NULL;
7301         const char *p;
7302         uint32_t attrs;
7303         NTSTATUS status;
7304         bool src_has_wcard = False;
7305         bool dest_has_wcard = False;
7306         TALLOC_CTX *ctx = talloc_tos();
7307         struct smb_filename *smb_fname_src = NULL;
7308         struct smb_filename *smb_fname_dst = NULL;
7309         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7310                 (req->posix_pathnames ?
7311                         UCF_UNIX_NAME_LOOKUP :
7312                         UCF_COND_ALLOW_WCARD_LCOMP);
7313         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7314                 UCF_SAVE_LCOMP |
7315                 (req->posix_pathnames ?
7316                         0 :
7317                         UCF_COND_ALLOW_WCARD_LCOMP);
7318         bool stream_rename = false;
7319
7320         START_PROFILE(SMBmv);
7321
7322         if (req->wct < 1) {
7323                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7324                 goto out;
7325         }
7326
7327         attrs = SVAL(req->vwv+0, 0);
7328
7329         p = (const char *)req->buf + 1;
7330         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7331                                        &status, &src_has_wcard);
7332         if (!NT_STATUS_IS_OK(status)) {
7333                 reply_nterror(req, status);
7334                 goto out;
7335         }
7336         p++;
7337         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7338                                        &status, &dest_has_wcard);
7339         if (!NT_STATUS_IS_OK(status)) {
7340                 reply_nterror(req, status);
7341                 goto out;
7342         }
7343
7344         if (!req->posix_pathnames) {
7345                 /* The newname must begin with a ':' if the
7346                    name contains a ':'. */
7347                 if (strchr_m(name, ':')) {
7348                         if (newname[0] != ':') {
7349                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7350                                 goto out;
7351                         }
7352                         stream_rename = true;
7353                 }
7354         }
7355
7356         status = filename_convert(ctx,
7357                                   conn,
7358                                   name,
7359                                   src_ucf_flags,
7360                                   &src_has_wcard,
7361                                   &smb_fname_src);
7362
7363         if (!NT_STATUS_IS_OK(status)) {
7364                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7365                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7366                                         ERRSRV, ERRbadpath);
7367                         goto out;
7368                 }
7369                 reply_nterror(req, status);
7370                 goto out;
7371         }
7372
7373         status = filename_convert(ctx,
7374                                   conn,
7375                                   newname,
7376                                   dst_ucf_flags,
7377                                   &dest_has_wcard,
7378                                   &smb_fname_dst);
7379
7380         if (!NT_STATUS_IS_OK(status)) {
7381                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7382                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7383                                         ERRSRV, ERRbadpath);
7384                         goto out;
7385                 }
7386                 reply_nterror(req, status);
7387                 goto out;
7388         }
7389
7390         if (stream_rename) {
7391                 /* smb_fname_dst->base_name must be the same as
7392                    smb_fname_src->base_name. */
7393                 TALLOC_FREE(smb_fname_dst->base_name);
7394                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7395                                                 smb_fname_src->base_name);
7396                 if (!smb_fname_dst->base_name) {
7397                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7398                         goto out;
7399                 }
7400         }
7401
7402         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7403                  smb_fname_str_dbg(smb_fname_dst)));
7404
7405         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7406                                   attrs, False, src_has_wcard, dest_has_wcard,
7407                                   DELETE_ACCESS);
7408         if (!NT_STATUS_IS_OK(status)) {
7409                 if (open_was_deferred(req->xconn, req->mid)) {
7410                         /* We have re-scheduled this call. */
7411                         goto out;
7412                 }
7413                 reply_nterror(req, status);
7414                 goto out;
7415         }
7416
7417         reply_outbuf(req, 0, 0);
7418  out:
7419         TALLOC_FREE(smb_fname_src);
7420         TALLOC_FREE(smb_fname_dst);
7421         END_PROFILE(SMBmv);
7422         return;
7423 }
7424
7425 /*******************************************************************
7426  Copy a file as part of a reply_copy.
7427 ******************************************************************/
7428
7429 /*
7430  * TODO: check error codes on all callers
7431  */
7432
7433 NTSTATUS copy_file(TALLOC_CTX *ctx,
7434                         connection_struct *conn,
7435                         struct smb_filename *smb_fname_src,
7436                         struct smb_filename *smb_fname_dst,
7437                         int ofun,
7438                         int count,
7439                         bool target_is_directory)
7440 {
7441         struct smb_filename *smb_fname_dst_tmp = NULL;
7442         off_t ret=-1;
7443         files_struct *fsp1,*fsp2;
7444         uint32_t dosattrs;
7445         uint32_t new_create_disposition;
7446         NTSTATUS status;
7447
7448
7449         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7450         if (smb_fname_dst_tmp == NULL) {
7451                 return NT_STATUS_NO_MEMORY;
7452         }
7453
7454         /*
7455          * If the target is a directory, extract the last component from the
7456          * src filename and append it to the dst filename
7457          */
7458         if (target_is_directory) {
7459                 const char *p;
7460
7461                 /* dest/target can't be a stream if it's a directory. */
7462                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7463
7464                 p = strrchr_m(smb_fname_src->base_name,'/');
7465                 if (p) {
7466                         p++;
7467                 } else {
7468                         p = smb_fname_src->base_name;
7469                 }
7470                 smb_fname_dst_tmp->base_name =
7471                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7472                                            p);
7473                 if (!smb_fname_dst_tmp->base_name) {
7474                         status = NT_STATUS_NO_MEMORY;
7475                         goto out;
7476                 }
7477         }
7478
7479         status = vfs_file_exist(conn, smb_fname_src);
7480         if (!NT_STATUS_IS_OK(status)) {
7481                 goto out;
7482         }
7483
7484         if (!target_is_directory && count) {
7485                 new_create_disposition = FILE_OPEN;
7486         } else {
7487                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7488                                                  0, ofun,
7489                                                  NULL, NULL,
7490                                                  &new_create_disposition,
7491                                                  NULL,
7492                                                  NULL)) {
7493                         status = NT_STATUS_INVALID_PARAMETER;
7494                         goto out;
7495                 }
7496         }
7497
7498         /* Open the src file for reading. */
7499         status = SMB_VFS_CREATE_FILE(
7500                 conn,                                   /* conn */
7501                 NULL,                                   /* req */
7502                 0,                                      /* root_dir_fid */
7503                 smb_fname_src,                          /* fname */
7504                 FILE_GENERIC_READ,                      /* access_mask */
7505                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7506                 FILE_OPEN,                              /* create_disposition*/
7507                 0,                                      /* create_options */
7508                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7509                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7510                 NULL,                                   /* lease */
7511                 0,                                      /* allocation_size */
7512                 0,                                      /* private_flags */
7513                 NULL,                                   /* sd */
7514                 NULL,                                   /* ea_list */
7515                 &fsp1,                                  /* result */
7516                 NULL,                                   /* psbuf */
7517                 NULL, NULL);                            /* create context */
7518
7519         if (!NT_STATUS_IS_OK(status)) {
7520                 goto out;
7521         }
7522
7523         dosattrs = dos_mode(conn, smb_fname_src);
7524
7525         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7526                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7527         }
7528
7529         /* Open the dst file for writing. */
7530         status = SMB_VFS_CREATE_FILE(
7531                 conn,                                   /* conn */
7532                 NULL,                                   /* req */
7533                 0,                                      /* root_dir_fid */
7534                 smb_fname_dst,                          /* fname */
7535                 FILE_GENERIC_WRITE,                     /* access_mask */
7536                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7537                 new_create_disposition,                 /* create_disposition*/
7538                 0,                                      /* create_options */
7539                 dosattrs,                               /* file_attributes */
7540                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7541                 NULL,                                   /* lease */
7542                 0,                                      /* allocation_size */
7543                 0,                                      /* private_flags */
7544                 NULL,                                   /* sd */
7545                 NULL,                                   /* ea_list */
7546                 &fsp2,                                  /* result */
7547                 NULL,                                   /* psbuf */
7548                 NULL, NULL);                            /* create context */
7549
7550         if (!NT_STATUS_IS_OK(status)) {
7551                 close_file(NULL, fsp1, ERROR_CLOSE);
7552                 goto out;
7553         }
7554
7555         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7556                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7557                 if (ret == -1) {
7558                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7559                                 strerror(errno)));
7560                         status = map_nt_error_from_unix(errno);
7561                         close_file(NULL, fsp1, ERROR_CLOSE);
7562                         close_file(NULL, fsp2, ERROR_CLOSE);
7563                         goto out;
7564                 }
7565         }
7566
7567         /* Do the actual copy. */
7568         if (smb_fname_src->st.st_ex_size) {
7569                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7570         } else {
7571                 ret = 0;
7572         }
7573
7574         close_file(NULL, fsp1, NORMAL_CLOSE);
7575
7576         /* Ensure the modtime is set correctly on the destination file. */
7577         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7578
7579         /*
7580          * As we are opening fsp1 read-only we only expect
7581          * an error on close on fsp2 if we are out of space.
7582          * Thus we don't look at the error return from the
7583          * close of fsp1.
7584          */
7585         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7586
7587         if (!NT_STATUS_IS_OK(status)) {
7588                 goto out;
7589         }
7590
7591         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7592                 status = NT_STATUS_DISK_FULL;
7593                 goto out;
7594         }
7595
7596         status = NT_STATUS_OK;
7597
7598  out:
7599         TALLOC_FREE(smb_fname_dst_tmp);
7600         return status;
7601 }
7602
7603 /****************************************************************************
7604  Reply to a file copy.
7605 ****************************************************************************/
7606
7607 void reply_copy(struct smb_request *req)
7608 {
7609         connection_struct *conn = req->conn;
7610         struct smb_filename *smb_fname_src = NULL;
7611         struct smb_filename *smb_fname_src_dir = NULL;
7612         struct smb_filename *smb_fname_dst = NULL;
7613         char *fname_src = NULL;
7614         char *fname_dst = NULL;
7615         char *fname_src_mask = NULL;
7616         char *fname_src_dir = NULL;
7617         const char *p;
7618         int count=0;
7619         int error = ERRnoaccess;
7620         int tid2;
7621         int ofun;
7622         int flags;
7623         bool target_is_directory=False;
7624         bool source_has_wild = False;
7625         bool dest_has_wild = False;
7626         NTSTATUS status;
7627         uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7628                 ucf_flags_from_smb_request(req);
7629         uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7630                 ucf_flags_from_smb_request(req);
7631         TALLOC_CTX *ctx = talloc_tos();
7632
7633         START_PROFILE(SMBcopy);
7634
7635         if (req->wct < 3) {
7636                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7637                 goto out;
7638         }
7639
7640         tid2 = SVAL(req->vwv+0, 0);
7641         ofun = SVAL(req->vwv+1, 0);
7642         flags = SVAL(req->vwv+2, 0);
7643
7644         p = (const char *)req->buf;
7645         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7646                                        &status, &source_has_wild);
7647         if (!NT_STATUS_IS_OK(status)) {
7648                 reply_nterror(req, status);
7649                 goto out;
7650         }
7651         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7652                                        &status, &dest_has_wild);
7653         if (!NT_STATUS_IS_OK(status)) {
7654                 reply_nterror(req, status);
7655                 goto out;
7656         }
7657
7658         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7659
7660         if (tid2 != conn->cnum) {
7661                 /* can't currently handle inter share copies XXXX */
7662                 DEBUG(3,("Rejecting inter-share copy\n"));
7663                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7664                 goto out;
7665         }
7666
7667         status = filename_convert(ctx, conn,
7668                                   fname_src,
7669                                   ucf_flags_src,
7670                                   &source_has_wild,
7671                                   &smb_fname_src);
7672         if (!NT_STATUS_IS_OK(status)) {
7673                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7674                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7675                                         ERRSRV, ERRbadpath);
7676                         goto out;
7677                 }
7678                 reply_nterror(req, status);
7679                 goto out;
7680         }
7681
7682         status = filename_convert(ctx, conn,
7683                                   fname_dst,
7684                                   ucf_flags_dst,
7685                                   &dest_has_wild,
7686                                   &smb_fname_dst);
7687         if (!NT_STATUS_IS_OK(status)) {
7688                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7689                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7690                                         ERRSRV, ERRbadpath);
7691                         goto out;
7692                 }
7693                 reply_nterror(req, status);
7694                 goto out;
7695         }
7696
7697         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7698
7699         if ((flags&1) && target_is_directory) {
7700                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7701                 goto out;
7702         }
7703
7704         if ((flags&2) && !target_is_directory) {
7705                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7706                 goto out;
7707         }
7708
7709         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7710                 /* wants a tree copy! XXXX */
7711                 DEBUG(3,("Rejecting tree copy\n"));
7712                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7713                 goto out;
7714         }
7715
7716         /* Split up the directory from the filename/mask. */
7717         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7718                                       &fname_src_dir, &fname_src_mask);
7719         if (!NT_STATUS_IS_OK(status)) {
7720                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7721                 goto out;
7722         }
7723
7724         /*
7725          * We should only check the mangled cache
7726          * here if unix_convert failed. This means
7727          * that the path in 'mask' doesn't exist
7728          * on the file system and so we need to look
7729          * for a possible mangle. This patch from
7730          * Tine Smukavec <valentin.smukavec@hermes.si>.
7731          */
7732         if (!VALID_STAT(smb_fname_src->st) &&
7733             mangle_is_mangled(fname_src_mask, conn->params)) {
7734                 char *new_mask = NULL;
7735                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7736                                             &new_mask, conn->params);
7737
7738                 /* Use demangled name if one was successfully found. */
7739                 if (new_mask) {
7740                         TALLOC_FREE(fname_src_mask);
7741                         fname_src_mask = new_mask;
7742                 }
7743         }
7744
7745         if (!source_has_wild) {
7746
7747                 /*
7748                  * Only one file needs to be copied. Append the mask back onto
7749                  * the directory.
7750                  */
7751                 TALLOC_FREE(smb_fname_src->base_name);
7752                 if (ISDOT(fname_src_dir)) {
7753                         /* Ensure we use canonical names on open. */
7754                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7755                                                         "%s",
7756                                                         fname_src_mask);
7757                 } else {
7758                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7759                                                         "%s/%s",
7760                                                         fname_src_dir,
7761                                                         fname_src_mask);
7762                 }
7763                 if (!smb_fname_src->base_name) {
7764                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7765                         goto out;
7766                 }
7767
7768                 if (dest_has_wild) {
7769                         char *fname_dst_mod = NULL;
7770                         if (!resolve_wildcards(smb_fname_dst,
7771                                                smb_fname_src->base_name,
7772                                                smb_fname_dst->base_name,
7773                                                &fname_dst_mod)) {
7774                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7775                                 goto out;
7776                         }
7777                         TALLOC_FREE(smb_fname_dst->base_name);
7778                         smb_fname_dst->base_name = fname_dst_mod;
7779                 }
7780
7781                 status = check_name(conn, smb_fname_src);
7782                 if (!NT_STATUS_IS_OK(status)) {
7783                         reply_nterror(req, status);
7784                         goto out;
7785                 }
7786
7787                 status = check_name(conn, smb_fname_dst);
7788                 if (!NT_STATUS_IS_OK(status)) {
7789                         reply_nterror(req, status);
7790                         goto out;
7791                 }
7792
7793                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7794                                    ofun, count, target_is_directory);
7795
7796                 if(!NT_STATUS_IS_OK(status)) {
7797                         reply_nterror(req, status);
7798                         goto out;
7799                 } else {
7800                         count++;
7801                 }
7802         } else {
7803                 struct smb_Dir *dir_hnd = NULL;
7804                 const char *dname = NULL;
7805                 char *talloced = NULL;
7806                 long offset = 0;
7807
7808                 /*
7809                  * There is a wildcard that requires us to actually read the
7810                  * src dir and copy each file matching the mask to the dst.
7811                  * Right now streams won't be copied, but this could
7812                  * presumably be added with a nested loop for reach dir entry.
7813                  */
7814                 SMB_ASSERT(!smb_fname_src->stream_name);
7815                 SMB_ASSERT(!smb_fname_dst->stream_name);
7816
7817                 smb_fname_src->stream_name = NULL;
7818                 smb_fname_dst->stream_name = NULL;
7819
7820                 if (strequal(fname_src_mask,"????????.???")) {
7821                         TALLOC_FREE(fname_src_mask);
7822                         fname_src_mask = talloc_strdup(ctx, "*");
7823                         if (!fname_src_mask) {
7824                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7825                                 goto out;
7826                         }
7827                 }
7828
7829                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7830                                         fname_src_dir,
7831                                         NULL,
7832                                         NULL,
7833                                         smb_fname_src->flags);
7834                 if (smb_fname_src_dir == NULL) {
7835                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7836                         goto out;
7837                 }
7838
7839                 status = check_name(conn, smb_fname_src_dir);
7840                 if (!NT_STATUS_IS_OK(status)) {
7841                         reply_nterror(req, status);
7842                         goto out;
7843                 }
7844
7845                 dir_hnd = OpenDir(ctx,
7846                                 conn,
7847                                 smb_fname_src_dir,
7848                                 fname_src_mask,
7849                                 0);
7850                 if (dir_hnd == NULL) {
7851                         status = map_nt_error_from_unix(errno);
7852                         reply_nterror(req, status);
7853                         goto out;
7854                 }
7855
7856                 error = ERRbadfile;
7857
7858                 /* Iterate over the src dir copying each entry to the dst. */
7859                 while ((dname = ReadDirName(dir_hnd, &offset,
7860                                             &smb_fname_src->st, &talloced))) {
7861                         char *destname = NULL;
7862
7863                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7864                                 TALLOC_FREE(talloced);
7865                                 continue;
7866                         }
7867
7868                         if (!is_visible_file(conn, fname_src_dir, dname,
7869                                              &smb_fname_src->st, false)) {
7870                                 TALLOC_FREE(talloced);
7871                                 continue;
7872                         }
7873
7874                         if(!mask_match(dname, fname_src_mask,
7875                                        conn->case_sensitive)) {
7876                                 TALLOC_FREE(talloced);
7877                                 continue;
7878                         }
7879
7880                         error = ERRnoaccess;
7881
7882                         /* Get the src smb_fname struct setup. */
7883                         TALLOC_FREE(smb_fname_src->base_name);
7884                         if (ISDOT(fname_src_dir)) {
7885                                 /* Ensure we use canonical names on open. */
7886                                 smb_fname_src->base_name =
7887                                         talloc_asprintf(smb_fname_src, "%s",
7888                                                 dname);
7889                         } else {
7890                                 smb_fname_src->base_name =
7891                                         talloc_asprintf(smb_fname_src, "%s/%s",
7892                                                 fname_src_dir, dname);
7893                         }
7894
7895                         if (!smb_fname_src->base_name) {
7896                                 TALLOC_FREE(dir_hnd);
7897                                 TALLOC_FREE(talloced);
7898                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7899                                 goto out;
7900                         }
7901
7902                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7903                                                smb_fname_dst->base_name,
7904                                                &destname)) {
7905                                 TALLOC_FREE(talloced);
7906                                 continue;
7907                         }
7908                         if (!destname) {
7909                                 TALLOC_FREE(dir_hnd);
7910                                 TALLOC_FREE(talloced);
7911                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7912                                 goto out;
7913                         }
7914
7915                         TALLOC_FREE(smb_fname_dst->base_name);
7916                         smb_fname_dst->base_name = destname;
7917
7918                         status = check_name(conn, smb_fname_src);
7919                         if (!NT_STATUS_IS_OK(status)) {
7920                                 TALLOC_FREE(dir_hnd);
7921                                 TALLOC_FREE(talloced);
7922                                 reply_nterror(req, status);
7923                                 goto out;
7924                         }
7925
7926                         status = check_name(conn, smb_fname_dst);
7927                         if (!NT_STATUS_IS_OK(status)) {
7928                                 TALLOC_FREE(dir_hnd);
7929                                 TALLOC_FREE(talloced);
7930                                 reply_nterror(req, status);
7931                                 goto out;
7932                         }
7933
7934                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7935                                 smb_fname_src->base_name,
7936                                 smb_fname_dst->base_name));
7937
7938                         status = copy_file(ctx, conn, smb_fname_src,
7939                                            smb_fname_dst, ofun, count,
7940                                            target_is_directory);
7941                         if (NT_STATUS_IS_OK(status)) {
7942                                 count++;
7943                         }
7944
7945                         TALLOC_FREE(talloced);
7946                 }
7947                 TALLOC_FREE(dir_hnd);
7948         }
7949
7950         if (count == 0) {
7951                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7952                 goto out;
7953         }
7954
7955         reply_outbuf(req, 1, 0);
7956         SSVAL(req->outbuf,smb_vwv0,count);
7957  out:
7958         TALLOC_FREE(smb_fname_src);
7959         TALLOC_FREE(smb_fname_src_dir);
7960         TALLOC_FREE(smb_fname_dst);
7961         TALLOC_FREE(fname_src);
7962         TALLOC_FREE(fname_dst);
7963         TALLOC_FREE(fname_src_mask);
7964         TALLOC_FREE(fname_src_dir);
7965
7966         END_PROFILE(SMBcopy);
7967         return;
7968 }
7969
7970 #undef DBGC_CLASS
7971 #define DBGC_CLASS DBGC_LOCKING
7972
7973 /****************************************************************************
7974  Get a lock pid, dealing with large count requests.
7975 ****************************************************************************/
7976
7977 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7978                     bool large_file_format)
7979 {
7980         if(!large_file_format)
7981                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7982         else
7983                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7984 }
7985
7986 /****************************************************************************
7987  Get a lock count, dealing with large count requests.
7988 ****************************************************************************/
7989
7990 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7991                         bool large_file_format)
7992 {
7993         uint64_t count = 0;
7994
7995         if(!large_file_format) {
7996                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7997         } else {
7998                 /*
7999                  * No BVAL, this is reversed!
8000                  */
8001                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8002                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8003         }
8004
8005         return count;
8006 }
8007
8008 /****************************************************************************
8009  Get a lock offset, dealing with large offset requests.
8010 ****************************************************************************/
8011
8012 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8013                          bool large_file_format)
8014 {
8015         uint64_t offset = 0;
8016
8017         if(!large_file_format) {
8018                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8019         } else {
8020                 /*
8021                  * No BVAL, this is reversed!
8022                  */
8023                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8024                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8025         }
8026
8027         return offset;
8028 }
8029
8030 NTSTATUS smbd_do_locking(struct smb_request *req,
8031                          files_struct *fsp,
8032                          uint8_t type,
8033                          int32_t timeout,
8034                          uint16_t num_locks,
8035                          struct smbd_lock_element *locks,
8036                          bool *async)
8037 {
8038         connection_struct *conn = req->conn;
8039         int i;
8040         NTSTATUS status = NT_STATUS_OK;
8041
8042         *async = false;
8043
8044         /* Setup the timeout in seconds. */
8045
8046         if (!lp_blocking_locks(SNUM(conn))) {
8047                 timeout = 0;
8048         }
8049
8050         for(i = 0; i < (int)num_locks; i++) {
8051                 struct smbd_lock_element *e = &locks[i];
8052
8053                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8054                           "%llu, file %s timeout = %d\n",
8055                           (double)e->offset,
8056                           (double)e->count,
8057                           (unsigned long long)e->smblctx,
8058                           fsp_str_dbg(fsp),
8059                           (int)timeout));
8060
8061                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8062                         struct blocking_lock_record *blr = NULL;
8063
8064                         if (num_locks > 1) {
8065                                 /*
8066                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8067                                  * if the lock vector contains one entry. When given multiple cancel
8068                                  * requests in a single PDU we expect the server to return an
8069                                  * error. Windows servers seem to accept the request but only
8070                                  * cancel the first lock.
8071                                  * JRA - Do what Windows does (tm) :-).
8072                                  */
8073
8074 #if 0
8075                                 /* MS-CIFS (2.2.4.32.1) behavior. */
8076                                 return NT_STATUS_DOS(ERRDOS,
8077                                                 ERRcancelviolation);
8078 #else
8079                                 /* Windows behavior. */
8080                                 if (i != 0) {
8081                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
8082                                                 "cancel request\n"));
8083                                         continue;
8084                                 }
8085 #endif
8086                         }
8087
8088                         if (lp_blocking_locks(SNUM(conn))) {
8089
8090                                 /* Schedule a message to ourselves to
8091                                    remove the blocking lock record and
8092                                    return the right error. */
8093
8094                                 blr = blocking_lock_cancel_smb1(fsp,
8095                                                 e->smblctx,
8096                                                 e->offset,
8097                                                 e->count,
8098                                                 WINDOWS_LOCK,
8099                                                 type,
8100                                                 NT_STATUS_FILE_LOCK_CONFLICT);
8101                                 if (blr == NULL) {
8102                                         return NT_STATUS_DOS(
8103                                                         ERRDOS,
8104                                                         ERRcancelviolation);
8105                                 }
8106                         }
8107                         /* Remove a matching pending lock. */
8108                         status = do_lock_cancel(fsp,
8109                                                 e->smblctx,
8110                                                 e->count,
8111                                                 e->offset,
8112                                                 WINDOWS_LOCK);
8113                 } else {
8114                         bool blocking_lock = timeout ? true : false;
8115                         bool defer_lock = false;
8116                         struct byte_range_lock *br_lck;
8117                         uint64_t block_smblctx;
8118
8119                         br_lck = do_lock(req->sconn->msg_ctx,
8120                                         fsp,
8121                                         e->smblctx,
8122                                         e->count,
8123                                         e->offset, 
8124                                         e->brltype,
8125                                         WINDOWS_LOCK,
8126                                         blocking_lock,
8127                                         &status,
8128                                         &block_smblctx);
8129
8130                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8131                                 /* Windows internal resolution for blocking locks seems
8132                                    to be about 200ms... Don't wait for less than that. JRA. */
8133                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8134                                         timeout = lp_lock_spin_time();
8135                                 }
8136                                 defer_lock = true;
8137                         }
8138
8139                         /* If a lock sent with timeout of zero would fail, and
8140                          * this lock has been requested multiple times,
8141                          * according to brl_lock_failed() we convert this
8142                          * request to a blocking lock with a timeout of between
8143                          * 150 - 300 milliseconds.
8144                          *
8145                          * If lp_lock_spin_time() has been set to 0, we skip
8146                          * this blocking retry and fail immediately.
8147                          *
8148                          * Replacement for do_lock_spin(). JRA. */
8149
8150                         if (!req->sconn->using_smb2 &&
8151                             br_lck && lp_blocking_locks(SNUM(conn)) &&
8152                             lp_lock_spin_time() && !blocking_lock &&
8153                             NT_STATUS_EQUAL((status),
8154                                 NT_STATUS_FILE_LOCK_CONFLICT))
8155                         {
8156                                 defer_lock = true;
8157                                 timeout = lp_lock_spin_time();
8158                         }
8159
8160                         if (br_lck && defer_lock) {
8161                                 /*
8162                                  * A blocking lock was requested. Package up
8163                                  * this smb into a queued request and push it
8164                                  * onto the blocking lock queue.
8165                                  */
8166                                 if(push_blocking_lock_request(br_lck,
8167                                                         req,
8168                                                         fsp,
8169                                                         timeout,
8170                                                         i,
8171                                                         e->smblctx,
8172                                                         e->brltype,
8173                                                         WINDOWS_LOCK,
8174                                                         e->offset,
8175                                                         e->count,
8176                                                         block_smblctx)) {
8177                                         TALLOC_FREE(br_lck);
8178                                         *async = true;
8179                                         return NT_STATUS_OK;
8180                                 }
8181                         }
8182
8183                         TALLOC_FREE(br_lck);
8184                 }
8185
8186                 if (!NT_STATUS_IS_OK(status)) {
8187                         break;
8188                 }
8189         }
8190
8191         /* If any of the above locks failed, then we must unlock
8192            all of the previous locks (X/Open spec). */
8193
8194         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8195
8196                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8197                         i = -1; /* we want to skip the for loop */
8198                 }
8199
8200                 /*
8201                  * Ensure we don't do a remove on the lock that just failed,
8202                  * as under POSIX rules, if we have a lock already there, we
8203                  * will delete it (and we shouldn't) .....
8204                  */
8205                 for(i--; i >= 0; i--) {
8206                         struct smbd_lock_element *e = &locks[i];
8207
8208                         do_unlock(req->sconn->msg_ctx,
8209                                 fsp,
8210                                 e->smblctx,
8211                                 e->count,
8212                                 e->offset,
8213                                 WINDOWS_LOCK);
8214                 }
8215                 return status;
8216         }
8217
8218         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8219                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8220
8221         return NT_STATUS_OK;
8222 }
8223
8224 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8225                            files_struct *fsp,
8226                            uint16_t num_ulocks,
8227                            struct smbd_lock_element *ulocks)
8228 {
8229         int i;
8230
8231         for(i = 0; i < (int)num_ulocks; i++) {
8232                 struct smbd_lock_element *e = &ulocks[i];
8233                 NTSTATUS status;
8234
8235                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8236                           "pid %u, file %s\n", __func__,
8237                           (double)e->offset,
8238                           (double)e->count,
8239                           (unsigned int)e->smblctx,
8240                           fsp_str_dbg(fsp)));
8241
8242                 if (e->brltype != UNLOCK_LOCK) {
8243                         /* this can only happen with SMB2 */
8244                         return NT_STATUS_INVALID_PARAMETER;
8245                 }
8246
8247                 status = do_unlock(req->sconn->msg_ctx,
8248                                 fsp,
8249                                 e->smblctx,
8250                                 e->count,
8251                                 e->offset,
8252                                 WINDOWS_LOCK);
8253
8254                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8255                            nt_errstr(status)));
8256
8257                 if (!NT_STATUS_IS_OK(status)) {
8258                         return status;
8259                 }
8260         }
8261
8262         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8263                   num_ulocks));
8264
8265         return NT_STATUS_OK;
8266 }
8267
8268 /****************************************************************************
8269  Reply to a lockingX request.
8270 ****************************************************************************/
8271
8272 void reply_lockingX(struct smb_request *req)
8273 {
8274         connection_struct *conn = req->conn;
8275         files_struct *fsp;
8276         unsigned char locktype;
8277         unsigned char oplocklevel;
8278         uint16_t num_ulocks;
8279         uint16_t num_locks;
8280         int32_t lock_timeout;
8281         int i;
8282         const uint8_t *data;
8283         bool large_file_format;
8284         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8285         struct smbd_lock_element *ulocks;
8286         struct smbd_lock_element *locks;
8287         bool async = false;
8288
8289         START_PROFILE(SMBlockingX);
8290
8291         if (req->wct < 8) {
8292                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8293                 END_PROFILE(SMBlockingX);
8294                 return;
8295         }
8296
8297         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8298         locktype = CVAL(req->vwv+3, 0);
8299         oplocklevel = CVAL(req->vwv+3, 1);
8300         num_ulocks = SVAL(req->vwv+6, 0);
8301         num_locks = SVAL(req->vwv+7, 0);
8302         lock_timeout = IVAL(req->vwv+4, 0);
8303         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8304
8305         if (!check_fsp(conn, req, fsp)) {
8306                 END_PROFILE(SMBlockingX);
8307                 return;
8308         }
8309
8310         data = req->buf;
8311
8312         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8313                 /* we don't support these - and CANCEL_LOCK makes w2k
8314                    and XP reboot so I don't really want to be
8315                    compatible! (tridge) */
8316                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8317                 END_PROFILE(SMBlockingX);
8318                 return;
8319         }
8320
8321         /* Check if this is an oplock break on a file
8322            we have granted an oplock on.
8323         */
8324         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8325                 /* Client can insist on breaking to none. */
8326                 bool break_to_none = (oplocklevel == 0);
8327                 bool result;
8328
8329                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8330                          "for %s\n", (unsigned int)oplocklevel,
8331                          fsp_fnum_dbg(fsp)));
8332
8333                 /*
8334                  * Make sure we have granted an exclusive or batch oplock on
8335                  * this file.
8336                  */
8337
8338                 if (fsp->oplock_type == 0) {
8339
8340                         /* The Samba4 nbench simulator doesn't understand
8341                            the difference between break to level2 and break
8342                            to none from level2 - it sends oplock break
8343                            replies in both cases. Don't keep logging an error
8344                            message here - just ignore it. JRA. */
8345
8346                         DEBUG(5,("reply_lockingX: Error : oplock break from "
8347                                  "client for %s (oplock=%d) and no "
8348                                  "oplock granted on this file (%s).\n",
8349                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
8350                                  fsp_str_dbg(fsp)));
8351
8352                         /* if this is a pure oplock break request then don't
8353                          * send a reply */
8354                         if (num_locks == 0 && num_ulocks == 0) {
8355                                 END_PROFILE(SMBlockingX);
8356                                 return;
8357                         } else {
8358                                 END_PROFILE(SMBlockingX);
8359                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8360                                 return;
8361                         }
8362                 }
8363
8364                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8365                     (break_to_none)) {
8366                         result = remove_oplock(fsp);
8367                 } else {
8368                         result = downgrade_oplock(fsp);
8369                 }
8370
8371                 if (!result) {
8372                         DEBUG(0, ("reply_lockingX: error in removing "
8373                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
8374                         /* Hmmm. Is this panic justified? */
8375                         smb_panic("internal tdb error");
8376                 }
8377
8378                 /* if this is a pure oplock break request then don't send a
8379                  * reply */
8380                 if (num_locks == 0 && num_ulocks == 0) {
8381                         /* Sanity check - ensure a pure oplock break is not a
8382                            chained request. */
8383                         if (CVAL(req->vwv+0, 0) != 0xff) {
8384                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8385                                          "break is a chained %d request !\n",
8386                                          (unsigned int)CVAL(req->vwv+0, 0)));
8387                         }
8388                         END_PROFILE(SMBlockingX);
8389                         return;
8390                 }
8391         }
8392
8393         if (req->buflen <
8394             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8395                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8396                 END_PROFILE(SMBlockingX);
8397                 return;
8398         }
8399
8400         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8401         if (ulocks == NULL) {
8402                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403                 END_PROFILE(SMBlockingX);
8404                 return;
8405         }
8406
8407         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8408         if (locks == NULL) {
8409                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8410                 END_PROFILE(SMBlockingX);
8411                 return;
8412         }
8413
8414         /* Data now points at the beginning of the list
8415            of smb_unlkrng structs */
8416         for(i = 0; i < (int)num_ulocks; i++) {
8417                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8418                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8419                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8420                 ulocks[i].brltype = UNLOCK_LOCK;
8421         }
8422
8423         /* Now do any requested locks */
8424         data += ((large_file_format ? 20 : 10)*num_ulocks);
8425
8426         /* Data now points at the beginning of the list
8427            of smb_lkrng structs */
8428
8429         for(i = 0; i < (int)num_locks; i++) {
8430                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8431                 locks[i].count = get_lock_count(data, i, large_file_format);
8432                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8433
8434                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8435                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8436                                 locks[i].brltype = PENDING_READ_LOCK;
8437                         } else {
8438                                 locks[i].brltype = READ_LOCK;
8439                         }
8440                 } else {
8441                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8442                                 locks[i].brltype = PENDING_WRITE_LOCK;
8443                         } else {
8444                                 locks[i].brltype = WRITE_LOCK;
8445                         }
8446                 }
8447         }
8448
8449         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8450         if (!NT_STATUS_IS_OK(status)) {
8451                 END_PROFILE(SMBlockingX);
8452                 reply_nterror(req, status);
8453                 return;
8454         }
8455
8456         status = smbd_do_locking(req, fsp,
8457                                  locktype, lock_timeout,
8458                                  num_locks, locks,
8459                                  &async);
8460         if (!NT_STATUS_IS_OK(status)) {
8461                 END_PROFILE(SMBlockingX);
8462                 reply_nterror(req, status);
8463                 return;
8464         }
8465         if (async) {
8466                 END_PROFILE(SMBlockingX);
8467                 return;
8468         }
8469
8470         reply_outbuf(req, 2, 0);
8471         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8472         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8473
8474         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8475                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8476
8477         END_PROFILE(SMBlockingX);
8478 }
8479
8480 #undef DBGC_CLASS
8481 #define DBGC_CLASS DBGC_ALL
8482
8483 /****************************************************************************
8484  Reply to a SMBreadbmpx (read block multiplex) request.
8485  Always reply with an error, if someone has a platform really needs this,
8486  please contact vl@samba.org
8487 ****************************************************************************/
8488
8489 void reply_readbmpx(struct smb_request *req)
8490 {
8491         START_PROFILE(SMBreadBmpx);
8492         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8493         END_PROFILE(SMBreadBmpx);
8494         return;
8495 }
8496
8497 /****************************************************************************
8498  Reply to a SMBreadbs (read block multiplex secondary) request.
8499  Always reply with an error, if someone has a platform really needs this,
8500  please contact vl@samba.org
8501 ****************************************************************************/
8502
8503 void reply_readbs(struct smb_request *req)
8504 {
8505         START_PROFILE(SMBreadBs);
8506         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8507         END_PROFILE(SMBreadBs);
8508         return;
8509 }
8510
8511 /****************************************************************************
8512  Reply to a SMBsetattrE.
8513 ****************************************************************************/
8514
8515 void reply_setattrE(struct smb_request *req)
8516 {
8517         connection_struct *conn = req->conn;
8518         struct smb_file_time ft;
8519         files_struct *fsp;
8520         NTSTATUS status;
8521
8522         START_PROFILE(SMBsetattrE);
8523         ZERO_STRUCT(ft);
8524
8525         if (req->wct < 7) {
8526                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8527                 goto out;
8528         }
8529
8530         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8531
8532         if(!fsp || (fsp->conn != conn)) {
8533                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8534                 goto out;
8535         }
8536
8537         /*
8538          * Convert the DOS times into unix times.
8539          */
8540
8541         ft.atime = convert_time_t_to_timespec(
8542             srv_make_unix_date2(req->vwv+3));
8543         ft.mtime = convert_time_t_to_timespec(
8544             srv_make_unix_date2(req->vwv+5));
8545         ft.create_time = convert_time_t_to_timespec(
8546             srv_make_unix_date2(req->vwv+1));
8547
8548         reply_outbuf(req, 0, 0);
8549
8550         /* 
8551          * Patch from Ray Frush <frush@engr.colostate.edu>
8552          * Sometimes times are sent as zero - ignore them.
8553          */
8554
8555         /* Ensure we have a valid stat struct for the source. */
8556         status = vfs_stat_fsp(fsp);
8557         if (!NT_STATUS_IS_OK(status)) {
8558                 reply_nterror(req, status);
8559                 goto out;
8560         }
8561
8562         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8563                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8564                 goto out;
8565         }
8566
8567         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8568         if (!NT_STATUS_IS_OK(status)) {
8569                 reply_nterror(req, status);
8570                 goto out;
8571         }
8572
8573         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8574                " createtime=%u\n",
8575                 fsp_fnum_dbg(fsp),
8576                 (unsigned int)ft.atime.tv_sec,
8577                 (unsigned int)ft.mtime.tv_sec,
8578                 (unsigned int)ft.create_time.tv_sec
8579                 ));
8580  out:
8581         END_PROFILE(SMBsetattrE);
8582         return;
8583 }
8584
8585
8586 /* Back from the dead for OS/2..... JRA. */
8587
8588 /****************************************************************************
8589  Reply to a SMBwritebmpx (write block multiplex primary) request.
8590  Always reply with an error, if someone has a platform really needs this,
8591  please contact vl@samba.org
8592 ****************************************************************************/
8593
8594 void reply_writebmpx(struct smb_request *req)
8595 {
8596         START_PROFILE(SMBwriteBmpx);
8597         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8598         END_PROFILE(SMBwriteBmpx);
8599         return;
8600 }
8601
8602 /****************************************************************************
8603  Reply to a SMBwritebs (write block multiplex secondary) request.
8604  Always reply with an error, if someone has a platform really needs this,
8605  please contact vl@samba.org
8606 ****************************************************************************/
8607
8608 void reply_writebs(struct smb_request *req)
8609 {
8610         START_PROFILE(SMBwriteBs);
8611         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8612         END_PROFILE(SMBwriteBs);
8613         return;
8614 }
8615
8616 /****************************************************************************
8617  Reply to a SMBgetattrE.
8618 ****************************************************************************/
8619
8620 void reply_getattrE(struct smb_request *req)
8621 {
8622         connection_struct *conn = req->conn;
8623         int mode;
8624         files_struct *fsp;
8625         struct timespec create_ts;
8626
8627         START_PROFILE(SMBgetattrE);
8628
8629         if (req->wct < 1) {
8630                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8631                 END_PROFILE(SMBgetattrE);
8632                 return;
8633         }
8634
8635         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8636
8637         if(!fsp || (fsp->conn != conn)) {
8638                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8639                 END_PROFILE(SMBgetattrE);
8640                 return;
8641         }
8642
8643         /* Do an fstat on this file */
8644         if(fsp_stat(fsp)) {
8645                 reply_nterror(req, map_nt_error_from_unix(errno));
8646                 END_PROFILE(SMBgetattrE);
8647                 return;
8648         }
8649
8650         mode = dos_mode(conn, fsp->fsp_name);
8651
8652         /*
8653          * Convert the times into dos times. Set create
8654          * date to be last modify date as UNIX doesn't save
8655          * this.
8656          */
8657
8658         reply_outbuf(req, 11, 0);
8659
8660         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8661         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8662         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8663                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8664         /* Should we check pending modtime here ? JRA */
8665         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8666                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8667
8668         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8669                 SIVAL(req->outbuf, smb_vwv6, 0);
8670                 SIVAL(req->outbuf, smb_vwv8, 0);
8671         } else {
8672                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8673                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8674                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8675         }
8676         SSVAL(req->outbuf,smb_vwv10, mode);
8677
8678         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8679
8680         END_PROFILE(SMBgetattrE);
8681         return;
8682 }