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