623f83b1250e787b4d363cd4382abe72f836913b
[vlendec/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 "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.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 int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3929 {
3930         int 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 /****************************************************************************
5271  Reply to a flush.
5272 ****************************************************************************/
5273
5274 void reply_flush(struct smb_request *req)
5275 {
5276         connection_struct *conn = req->conn;
5277         uint16_t fnum;
5278         files_struct *fsp;
5279
5280         START_PROFILE(SMBflush);
5281
5282         if (req->wct < 1) {
5283                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284                 return;
5285         }
5286
5287         fnum = SVAL(req->vwv+0, 0);
5288         fsp = file_fsp(req, fnum);
5289
5290         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5291                 return;
5292         }
5293
5294         if (!fsp) {
5295                 file_sync_all(conn);
5296         } else {
5297                 NTSTATUS status = sync_file(conn, fsp, True);
5298                 if (!NT_STATUS_IS_OK(status)) {
5299                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5300                                 fsp_str_dbg(fsp), nt_errstr(status)));
5301                         reply_nterror(req, status);
5302                         END_PROFILE(SMBflush);
5303                         return;
5304                 }
5305         }
5306
5307         reply_outbuf(req, 0, 0);
5308
5309         DEBUG(3,("flush\n"));
5310         END_PROFILE(SMBflush);
5311         return;
5312 }
5313
5314 /****************************************************************************
5315  Reply to a exit.
5316  conn POINTER CAN BE NULL HERE !
5317 ****************************************************************************/
5318
5319 void reply_exit(struct smb_request *req)
5320 {
5321         START_PROFILE(SMBexit);
5322
5323         file_close_pid(req->sconn, req->smbpid, req->vuid);
5324
5325         reply_outbuf(req, 0, 0);
5326
5327         DEBUG(3,("exit\n"));
5328
5329         END_PROFILE(SMBexit);
5330         return;
5331 }
5332
5333 struct reply_close_state {
5334         files_struct *fsp;
5335         struct smb_request *smbreq;
5336 };
5337
5338 static void do_smb1_close(struct tevent_req *req);
5339
5340 void reply_close(struct smb_request *req)
5341 {
5342         connection_struct *conn = req->conn;
5343         NTSTATUS status = NT_STATUS_OK;
5344         files_struct *fsp = NULL;
5345         START_PROFILE(SMBclose);
5346
5347         if (req->wct < 3) {
5348                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5349                 END_PROFILE(SMBclose);
5350                 return;
5351         }
5352
5353         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5354
5355         /*
5356          * We can only use check_fsp if we know it's not a directory.
5357          */
5358
5359         if (!check_fsp_open(conn, req, fsp)) {
5360                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5361                 END_PROFILE(SMBclose);
5362                 return;
5363         }
5364
5365         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5366                   fsp->is_directory ? "directory" : "file",
5367                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5368                   conn->num_files_open));
5369
5370         if (!fsp->is_directory) {
5371                 time_t t;
5372
5373                 /*
5374                  * Take care of any time sent in the close.
5375                  */
5376
5377                 t = srv_make_unix_date3(req->vwv+1);
5378                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5379         }
5380
5381         if (fsp->num_aio_requests != 0) {
5382
5383                 struct reply_close_state *state;
5384
5385                 DEBUG(10, ("closing with aio %u requests pending\n",
5386                            fsp->num_aio_requests));
5387
5388                 /*
5389                  * We depend on the aio_extra destructor to take care of this
5390                  * close request once fsp->num_aio_request drops to 0.
5391                  */
5392
5393                 fsp->deferred_close = tevent_wait_send(
5394                         fsp, fsp->conn->sconn->ev_ctx);
5395                 if (fsp->deferred_close == NULL) {
5396                         status = NT_STATUS_NO_MEMORY;
5397                         goto done;
5398                 }
5399
5400                 state = talloc(fsp, struct reply_close_state);
5401                 if (state == NULL) {
5402                         TALLOC_FREE(fsp->deferred_close);
5403                         status = NT_STATUS_NO_MEMORY;
5404                         goto done;
5405                 }
5406                 state->fsp = fsp;
5407                 state->smbreq = talloc_move(fsp, &req);
5408                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5409                                         state);
5410                 END_PROFILE(SMBclose);
5411                 return;
5412         }
5413
5414         /*
5415          * close_file() returns the unix errno if an error was detected on
5416          * close - normally this is due to a disk full error. If not then it
5417          * was probably an I/O error.
5418          */
5419
5420         status = close_file(req, fsp, NORMAL_CLOSE);
5421 done:
5422         if (!NT_STATUS_IS_OK(status)) {
5423                 reply_nterror(req, status);
5424                 END_PROFILE(SMBclose);
5425                 return;
5426         }
5427
5428         reply_outbuf(req, 0, 0);
5429         END_PROFILE(SMBclose);
5430         return;
5431 }
5432
5433 static void do_smb1_close(struct tevent_req *req)
5434 {
5435         struct reply_close_state *state = tevent_req_callback_data(
5436                 req, struct reply_close_state);
5437         struct smb_request *smbreq;
5438         NTSTATUS status;
5439         int ret;
5440
5441         ret = tevent_wait_recv(req);
5442         TALLOC_FREE(req);
5443         if (ret != 0) {
5444                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5445                            strerror(ret)));
5446                 /*
5447                  * Continue anyway, this should never happen
5448                  */
5449         }
5450
5451         /*
5452          * fsp->smb2_close_request right now is a talloc grandchild of
5453          * fsp. When we close_file(fsp), it would go with it. No chance to
5454          * reply...
5455          */
5456         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5457
5458         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5459         if (NT_STATUS_IS_OK(status)) {
5460                 reply_outbuf(smbreq, 0, 0);
5461         } else {
5462                 reply_nterror(smbreq, status);
5463         }
5464         if (!srv_send_smb(smbreq->xconn,
5465                         (char *)smbreq->outbuf,
5466                         true,
5467                         smbreq->seqnum+1,
5468                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5469                         NULL)) {
5470                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5471                                     "failed.");
5472         }
5473         TALLOC_FREE(smbreq);
5474 }
5475
5476 /****************************************************************************
5477  Reply to a writeclose (Core+ protocol).
5478 ****************************************************************************/
5479
5480 void reply_writeclose(struct smb_request *req)
5481 {
5482         connection_struct *conn = req->conn;
5483         size_t numtowrite;
5484         size_t remaining;
5485         ssize_t nwritten = -1;
5486         NTSTATUS close_status = NT_STATUS_OK;
5487         off_t startpos;
5488         const char *data;
5489         struct timespec mtime;
5490         files_struct *fsp;
5491         struct lock_struct lock;
5492
5493         START_PROFILE(SMBwriteclose);
5494
5495         if (req->wct < 6) {
5496                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5497                 END_PROFILE(SMBwriteclose);
5498                 return;
5499         }
5500
5501         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5502
5503         if (!check_fsp(conn, req, fsp)) {
5504                 END_PROFILE(SMBwriteclose);
5505                 return;
5506         }
5507         if (!CHECK_WRITE(fsp)) {
5508                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5509                 END_PROFILE(SMBwriteclose);
5510                 return;
5511         }
5512
5513         numtowrite = SVAL(req->vwv+1, 0);
5514         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5515         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5516         data = (const char *)req->buf + 1;
5517
5518         /*
5519          * Ensure client isn't asking us to write more than
5520          * they sent. CVE-2017-12163.
5521          */
5522         remaining = smbreq_bufrem(req, data);
5523         if (numtowrite > remaining) {
5524                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5525                 END_PROFILE(SMBwriteclose);
5526                 return;
5527         }
5528
5529         if (fsp->print_file == NULL) {
5530                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5531                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5532                     &lock);
5533
5534                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5535                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5536                         END_PROFILE(SMBwriteclose);
5537                         return;
5538                 }
5539         }
5540
5541         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5542
5543         set_close_write_time(fsp, mtime);
5544
5545         /*
5546          * More insanity. W2K only closes the file if writelen > 0.
5547          * JRA.
5548          */
5549
5550         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5551                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5552                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5553
5554         if (numtowrite) {
5555                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5556                          "file %s\n", fsp_str_dbg(fsp)));
5557                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5558                 fsp = NULL;
5559         }
5560
5561         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5562                 reply_nterror(req, NT_STATUS_DISK_FULL);
5563                 goto out;
5564         }
5565
5566         if(!NT_STATUS_IS_OK(close_status)) {
5567                 reply_nterror(req, close_status);
5568                 goto out;
5569         }
5570
5571         reply_outbuf(req, 1, 0);
5572
5573         SSVAL(req->outbuf,smb_vwv0,nwritten);
5574
5575 out:
5576
5577         END_PROFILE(SMBwriteclose);
5578         return;
5579 }
5580
5581 #undef DBGC_CLASS
5582 #define DBGC_CLASS DBGC_LOCKING
5583
5584 /****************************************************************************
5585  Reply to a lock.
5586 ****************************************************************************/
5587
5588 void reply_lock(struct smb_request *req)
5589 {
5590         connection_struct *conn = req->conn;
5591         uint64_t count,offset;
5592         NTSTATUS status;
5593         files_struct *fsp;
5594         struct byte_range_lock *br_lck = NULL;
5595
5596         START_PROFILE(SMBlock);
5597
5598         if (req->wct < 5) {
5599                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5600                 END_PROFILE(SMBlock);
5601                 return;
5602         }
5603
5604         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5605
5606         if (!check_fsp(conn, req, fsp)) {
5607                 END_PROFILE(SMBlock);
5608                 return;
5609         }
5610
5611         count = (uint64_t)IVAL(req->vwv+1, 0);
5612         offset = (uint64_t)IVAL(req->vwv+3, 0);
5613
5614         DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5615                  fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5616
5617         br_lck = do_lock(req->sconn->msg_ctx,
5618                         fsp,
5619                         (uint64_t)req->smbpid,
5620                         count,
5621                         offset,
5622                         WRITE_LOCK,
5623                         WINDOWS_LOCK,
5624                         False, /* Non-blocking lock. */
5625                         &status,
5626                         NULL);
5627
5628         TALLOC_FREE(br_lck);
5629
5630         if (NT_STATUS_V(status)) {
5631                 reply_nterror(req, status);
5632                 END_PROFILE(SMBlock);
5633                 return;
5634         }
5635
5636         reply_outbuf(req, 0, 0);
5637
5638         END_PROFILE(SMBlock);
5639         return;
5640 }
5641
5642 /****************************************************************************
5643  Reply to a unlock.
5644 ****************************************************************************/
5645
5646 void reply_unlock(struct smb_request *req)
5647 {
5648         connection_struct *conn = req->conn;
5649         uint64_t count,offset;
5650         NTSTATUS status;
5651         files_struct *fsp;
5652
5653         START_PROFILE(SMBunlock);
5654
5655         if (req->wct < 5) {
5656                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5657                 END_PROFILE(SMBunlock);
5658                 return;
5659         }
5660
5661         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5662
5663         if (!check_fsp(conn, req, fsp)) {
5664                 END_PROFILE(SMBunlock);
5665                 return;
5666         }
5667
5668         count = (uint64_t)IVAL(req->vwv+1, 0);
5669         offset = (uint64_t)IVAL(req->vwv+3, 0);
5670
5671         status = do_unlock(req->sconn->msg_ctx,
5672                         fsp,
5673                         (uint64_t)req->smbpid,
5674                         count,
5675                         offset,
5676                         WINDOWS_LOCK);
5677
5678         if (NT_STATUS_V(status)) {
5679                 reply_nterror(req, status);
5680                 END_PROFILE(SMBunlock);
5681                 return;
5682         }
5683
5684         DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5685                     fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5686
5687         reply_outbuf(req, 0, 0);
5688
5689         END_PROFILE(SMBunlock);
5690         return;
5691 }
5692
5693 #undef DBGC_CLASS
5694 #define DBGC_CLASS DBGC_ALL
5695
5696 /****************************************************************************
5697  Reply to a tdis.
5698  conn POINTER CAN BE NULL HERE !
5699 ****************************************************************************/
5700
5701 void reply_tdis(struct smb_request *req)
5702 {
5703         NTSTATUS status;
5704         connection_struct *conn = req->conn;
5705         struct smbXsrv_tcon *tcon;
5706
5707         START_PROFILE(SMBtdis);
5708
5709         if (!conn) {
5710                 DEBUG(4,("Invalid connection in tdis\n"));
5711                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5712                 END_PROFILE(SMBtdis);
5713                 return;
5714         }
5715
5716         tcon = conn->tcon;
5717         req->conn = NULL;
5718
5719         /*
5720          * TODO: cancel all outstanding requests on the tcon
5721          */
5722         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5723         if (!NT_STATUS_IS_OK(status)) {
5724                 DEBUG(0, ("reply_tdis: "
5725                           "smbXsrv_tcon_disconnect() failed: %s\n",
5726                           nt_errstr(status)));
5727                 /*
5728                  * If we hit this case, there is something completely
5729                  * wrong, so we better disconnect the transport connection.
5730                  */
5731                 END_PROFILE(SMBtdis);
5732                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5733                 return;
5734         }
5735
5736         TALLOC_FREE(tcon);
5737
5738         reply_outbuf(req, 0, 0);
5739         END_PROFILE(SMBtdis);
5740         return;
5741 }
5742
5743 /****************************************************************************
5744  Reply to a echo.
5745  conn POINTER CAN BE NULL HERE !
5746 ****************************************************************************/
5747
5748 void reply_echo(struct smb_request *req)
5749 {
5750         connection_struct *conn = req->conn;
5751         struct smb_perfcount_data local_pcd;
5752         struct smb_perfcount_data *cur_pcd;
5753         int smb_reverb;
5754         int seq_num;
5755
5756         START_PROFILE(SMBecho);
5757
5758         smb_init_perfcount_data(&local_pcd);
5759
5760         if (req->wct < 1) {
5761                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5762                 END_PROFILE(SMBecho);
5763                 return;
5764         }
5765
5766         smb_reverb = SVAL(req->vwv+0, 0);
5767
5768         reply_outbuf(req, 1, req->buflen);
5769
5770         /* copy any incoming data back out */
5771         if (req->buflen > 0) {
5772                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5773         }
5774
5775         if (smb_reverb > 100) {
5776                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5777                 smb_reverb = 100;
5778         }
5779
5780         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5781
5782                 /* this makes sure we catch the request pcd */
5783                 if (seq_num == smb_reverb) {
5784                         cur_pcd = &req->pcd;
5785                 } else {
5786                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5787                         cur_pcd = &local_pcd;
5788                 }
5789
5790                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5791
5792                 show_msg((char *)req->outbuf);
5793                 if (!srv_send_smb(req->xconn,
5794                                 (char *)req->outbuf,
5795                                 true, req->seqnum+1,
5796                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5797                                 cur_pcd))
5798                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5799         }
5800
5801         DEBUG(3,("echo %d times\n", smb_reverb));
5802
5803         TALLOC_FREE(req->outbuf);
5804
5805         END_PROFILE(SMBecho);
5806         return;
5807 }
5808
5809 /****************************************************************************
5810  Reply to a printopen.
5811 ****************************************************************************/
5812
5813 void reply_printopen(struct smb_request *req)
5814 {
5815         connection_struct *conn = req->conn;
5816         files_struct *fsp;
5817         NTSTATUS status;
5818
5819         START_PROFILE(SMBsplopen);
5820
5821         if (req->wct < 2) {
5822                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5823                 END_PROFILE(SMBsplopen);
5824                 return;
5825         }
5826
5827         if (!CAN_PRINT(conn)) {
5828                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5829                 END_PROFILE(SMBsplopen);
5830                 return;
5831         }
5832
5833         status = file_new(req, conn, &fsp);
5834         if(!NT_STATUS_IS_OK(status)) {
5835                 reply_nterror(req, status);
5836                 END_PROFILE(SMBsplopen);
5837                 return;
5838         }
5839
5840         /* Open for exclusive use, write only. */
5841         status = print_spool_open(fsp, NULL, req->vuid);
5842
5843         if (!NT_STATUS_IS_OK(status)) {
5844                 file_free(req, fsp);
5845                 reply_nterror(req, status);
5846                 END_PROFILE(SMBsplopen);
5847                 return;
5848         }
5849
5850         reply_outbuf(req, 1, 0);
5851         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5852
5853         DEBUG(3,("openprint fd=%d %s\n",
5854                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5855
5856         END_PROFILE(SMBsplopen);
5857         return;
5858 }
5859
5860 /****************************************************************************
5861  Reply to a printclose.
5862 ****************************************************************************/
5863
5864 void reply_printclose(struct smb_request *req)
5865 {
5866         connection_struct *conn = req->conn;
5867         files_struct *fsp;
5868         NTSTATUS status;
5869
5870         START_PROFILE(SMBsplclose);
5871
5872         if (req->wct < 1) {
5873                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5874                 END_PROFILE(SMBsplclose);
5875                 return;
5876         }
5877
5878         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5879
5880         if (!check_fsp(conn, req, fsp)) {
5881                 END_PROFILE(SMBsplclose);
5882                 return;
5883         }
5884
5885         if (!CAN_PRINT(conn)) {
5886                 reply_force_doserror(req, ERRSRV, ERRerror);
5887                 END_PROFILE(SMBsplclose);
5888                 return;
5889         }
5890
5891         DEBUG(3,("printclose fd=%d %s\n",
5892                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5893
5894         status = close_file(req, fsp, NORMAL_CLOSE);
5895
5896         if(!NT_STATUS_IS_OK(status)) {
5897                 reply_nterror(req, status);
5898                 END_PROFILE(SMBsplclose);
5899                 return;
5900         }
5901
5902         reply_outbuf(req, 0, 0);
5903
5904         END_PROFILE(SMBsplclose);
5905         return;
5906 }
5907
5908 /****************************************************************************
5909  Reply to a printqueue.
5910 ****************************************************************************/
5911
5912 void reply_printqueue(struct smb_request *req)
5913 {
5914         connection_struct *conn = req->conn;
5915         int max_count;
5916         int start_index;
5917
5918         START_PROFILE(SMBsplretq);
5919
5920         if (req->wct < 2) {
5921                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5922                 END_PROFILE(SMBsplretq);
5923                 return;
5924         }
5925
5926         max_count = SVAL(req->vwv+0, 0);
5927         start_index = SVAL(req->vwv+1, 0);
5928
5929         /* we used to allow the client to get the cnum wrong, but that
5930            is really quite gross and only worked when there was only
5931            one printer - I think we should now only accept it if they
5932            get it right (tridge) */
5933         if (!CAN_PRINT(conn)) {
5934                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5935                 END_PROFILE(SMBsplretq);
5936                 return;
5937         }
5938
5939         reply_outbuf(req, 2, 3);
5940         SSVAL(req->outbuf,smb_vwv0,0);
5941         SSVAL(req->outbuf,smb_vwv1,0);
5942         SCVAL(smb_buf(req->outbuf),0,1);
5943         SSVAL(smb_buf(req->outbuf),1,0);
5944
5945         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5946                  start_index, max_count));
5947
5948         {
5949                 TALLOC_CTX *mem_ctx = talloc_tos();
5950                 NTSTATUS status;
5951                 WERROR werr;
5952                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5953                 struct rpc_pipe_client *cli = NULL;
5954                 struct dcerpc_binding_handle *b = NULL;
5955                 struct policy_handle handle;
5956                 struct spoolss_DevmodeContainer devmode_ctr;
5957                 union spoolss_JobInfo *info;
5958                 uint32_t count;
5959                 uint32_t num_to_get;
5960                 uint32_t first;
5961                 uint32_t i;
5962
5963                 ZERO_STRUCT(handle);
5964
5965                 status = rpc_pipe_open_interface(mem_ctx,
5966                                                  &ndr_table_spoolss,
5967                                                  conn->session_info,
5968                                                  conn->sconn->remote_address,
5969                                                  conn->sconn->local_address,
5970                                                  conn->sconn->msg_ctx,
5971                                                  &cli);
5972                 if (!NT_STATUS_IS_OK(status)) {
5973                         DEBUG(0, ("reply_printqueue: "
5974                                   "could not connect to spoolss: %s\n",
5975                                   nt_errstr(status)));
5976                         reply_nterror(req, status);
5977                         goto out;
5978                 }
5979                 b = cli->binding_handle;
5980
5981                 ZERO_STRUCT(devmode_ctr);
5982
5983                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5984                                                 sharename,
5985                                                 NULL, devmode_ctr,
5986                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5987                                                 &handle,
5988                                                 &werr);
5989                 if (!NT_STATUS_IS_OK(status)) {
5990                         reply_nterror(req, status);
5991                         goto out;
5992                 }
5993                 if (!W_ERROR_IS_OK(werr)) {
5994                         reply_nterror(req, werror_to_ntstatus(werr));
5995                         goto out;
5996                 }
5997
5998                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5999                                                &handle,
6000                                                0, /* firstjob */
6001                                                0xff, /* numjobs */
6002                                                2, /* level */
6003                                                0, /* offered */
6004                                                &count,
6005                                                &info);
6006                 if (!W_ERROR_IS_OK(werr)) {
6007                         reply_nterror(req, werror_to_ntstatus(werr));
6008                         goto out;
6009                 }
6010
6011                 if (max_count > 0) {
6012                         first = start_index;
6013                 } else {
6014                         first = start_index + max_count + 1;
6015                 }
6016
6017                 if (first >= count) {
6018                         num_to_get = first;
6019                 } else {
6020                         num_to_get = first + MIN(ABS(max_count), count - first);
6021                 }
6022
6023                 for (i = first; i < num_to_get; i++) {
6024                         char blob[28];
6025                         char *p = blob;
6026                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6027                         int qstatus;
6028                         size_t len = 0;
6029                         uint16_t qrapjobid = pjobid_to_rap(sharename,
6030                                                         info[i].info2.job_id);
6031
6032                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
6033                                 qstatus = 2;
6034                         } else {
6035                                 qstatus = 3;
6036                         }
6037
6038                         srv_put_dos_date2(p, 0, qtime);
6039                         SCVAL(p, 4, qstatus);
6040                         SSVAL(p, 5, qrapjobid);
6041                         SIVAL(p, 7, info[i].info2.size);
6042                         SCVAL(p, 11, 0);
6043                         status = srvstr_push(blob, req->flags2, p+12,
6044                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
6045                         if (!NT_STATUS_IS_OK(status)) {
6046                                 reply_nterror(req, status);
6047                                 goto out;
6048                         }
6049                         if (message_push_blob(
6050                                     &req->outbuf,
6051                                     data_blob_const(
6052                                             blob, sizeof(blob))) == -1) {
6053                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6054                                 goto out;
6055                         }
6056                 }
6057
6058                 if (count > 0) {
6059                         SSVAL(req->outbuf,smb_vwv0,count);
6060                         SSVAL(req->outbuf,smb_vwv1,
6061                               (max_count>0?first+count:first-1));
6062                         SCVAL(smb_buf(req->outbuf),0,1);
6063                         SSVAL(smb_buf(req->outbuf),1,28*count);
6064                 }
6065
6066
6067                 DEBUG(3, ("%u entries returned in queue\n",
6068                           (unsigned)count));
6069
6070 out:
6071                 if (b && is_valid_policy_hnd(&handle)) {
6072                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6073                 }
6074
6075         }
6076
6077         END_PROFILE(SMBsplretq);
6078         return;
6079 }
6080
6081 /****************************************************************************
6082  Reply to a printwrite.
6083 ****************************************************************************/
6084
6085 void reply_printwrite(struct smb_request *req)
6086 {
6087         connection_struct *conn = req->conn;
6088         int numtowrite;
6089         const char *data;
6090         files_struct *fsp;
6091
6092         START_PROFILE(SMBsplwr);
6093
6094         if (req->wct < 1) {
6095                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6096                 END_PROFILE(SMBsplwr);
6097                 return;
6098         }
6099
6100         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6101
6102         if (!check_fsp(conn, req, fsp)) {
6103                 END_PROFILE(SMBsplwr);
6104                 return;
6105         }
6106
6107         if (!fsp->print_file) {
6108                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6109                 END_PROFILE(SMBsplwr);
6110                 return;
6111         }
6112
6113         if (!CHECK_WRITE(fsp)) {
6114                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6115                 END_PROFILE(SMBsplwr);
6116                 return;
6117         }
6118
6119         numtowrite = SVAL(req->buf, 1);
6120
6121         /*
6122          * This already protects us against CVE-2017-12163.
6123          */
6124         if (req->buflen < numtowrite + 3) {
6125                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6126                 END_PROFILE(SMBsplwr);
6127                 return;
6128         }
6129
6130         data = (const char *)req->buf + 3;
6131
6132         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6133                 reply_nterror(req, map_nt_error_from_unix(errno));
6134                 END_PROFILE(SMBsplwr);
6135                 return;
6136         }
6137
6138         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6139
6140         END_PROFILE(SMBsplwr);
6141         return;
6142 }
6143
6144 /****************************************************************************
6145  Reply to a mkdir.
6146 ****************************************************************************/
6147
6148 void reply_mkdir(struct smb_request *req)
6149 {
6150         connection_struct *conn = req->conn;
6151         struct smb_filename *smb_dname = NULL;
6152         char *directory = NULL;
6153         NTSTATUS status;
6154         uint32_t ucf_flags;
6155         TALLOC_CTX *ctx = talloc_tos();
6156
6157         START_PROFILE(SMBmkdir);
6158
6159         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6160                             STR_TERMINATE, &status);
6161         if (!NT_STATUS_IS_OK(status)) {
6162                 reply_nterror(req, status);
6163                 goto out;
6164         }
6165
6166         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6167         status = filename_convert(ctx, conn,
6168                                  directory,
6169                                  ucf_flags,
6170                                  NULL,
6171                                  &smb_dname);
6172         if (!NT_STATUS_IS_OK(status)) {
6173                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6174                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6175                                         ERRSRV, ERRbadpath);
6176                         goto out;
6177                 }
6178                 reply_nterror(req, status);
6179                 goto out;
6180         }
6181
6182         status = create_directory(conn, req, smb_dname);
6183
6184         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6185
6186         if (!NT_STATUS_IS_OK(status)) {
6187
6188                 if (!use_nt_status()
6189                     && NT_STATUS_EQUAL(status,
6190                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
6191                         /*
6192                          * Yes, in the DOS error code case we get a
6193                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6194                          * samba4 torture test.
6195                          */
6196                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6197                 }
6198
6199                 reply_nterror(req, status);
6200                 goto out;
6201         }
6202
6203         reply_outbuf(req, 0, 0);
6204
6205         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6206  out:
6207         TALLOC_FREE(smb_dname);
6208         END_PROFILE(SMBmkdir);
6209         return;
6210 }
6211
6212 /****************************************************************************
6213  Reply to a rmdir.
6214 ****************************************************************************/
6215
6216 void reply_rmdir(struct smb_request *req)
6217 {
6218         connection_struct *conn = req->conn;
6219         struct smb_filename *smb_dname = NULL;
6220         char *directory = NULL;
6221         NTSTATUS status;
6222         TALLOC_CTX *ctx = talloc_tos();
6223         files_struct *fsp = NULL;
6224         int info = 0;
6225         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6226         struct smbd_server_connection *sconn = req->sconn;
6227
6228         START_PROFILE(SMBrmdir);
6229
6230         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6231                             STR_TERMINATE, &status);
6232         if (!NT_STATUS_IS_OK(status)) {
6233                 reply_nterror(req, status);
6234                 goto out;
6235         }
6236
6237         status = filename_convert(ctx, conn,
6238                                  directory,
6239                                  ucf_flags,
6240                                  NULL,
6241                                  &smb_dname);
6242         if (!NT_STATUS_IS_OK(status)) {
6243                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6244                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6245                                         ERRSRV, ERRbadpath);
6246                         goto out;
6247                 }
6248                 reply_nterror(req, status);
6249                 goto out;
6250         }
6251
6252         if (is_ntfs_stream_smb_fname(smb_dname)) {
6253                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6254                 goto out;
6255         }
6256
6257         status = SMB_VFS_CREATE_FILE(
6258                 conn,                                   /* conn */
6259                 req,                                    /* req */
6260                 0,                                      /* root_dir_fid */
6261                 smb_dname,                              /* fname */
6262                 DELETE_ACCESS,                          /* access_mask */
6263                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6264                         FILE_SHARE_DELETE),
6265                 FILE_OPEN,                              /* create_disposition*/
6266                 FILE_DIRECTORY_FILE,                    /* create_options */
6267                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6268                 0,                                      /* oplock_request */
6269                 NULL,                                   /* lease */
6270                 0,                                      /* allocation_size */
6271                 0,                                      /* private_flags */
6272                 NULL,                                   /* sd */
6273                 NULL,                                   /* ea_list */
6274                 &fsp,                                   /* result */
6275                 &info,                                  /* pinfo */
6276                 NULL, NULL);                            /* create context */
6277
6278         if (!NT_STATUS_IS_OK(status)) {
6279                 if (open_was_deferred(req->xconn, req->mid)) {
6280                         /* We have re-scheduled this call. */
6281                         goto out;
6282                 }
6283                 reply_nterror(req, status);
6284                 goto out;
6285         }
6286
6287         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6288         if (!NT_STATUS_IS_OK(status)) {
6289                 close_file(req, fsp, ERROR_CLOSE);
6290                 reply_nterror(req, status);
6291                 goto out;
6292         }
6293
6294         if (!set_delete_on_close(fsp, true,
6295                         conn->session_info->security_token,
6296                         conn->session_info->unix_token)) {
6297                 close_file(req, fsp, ERROR_CLOSE);
6298                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6299                 goto out;
6300         }
6301
6302         status = close_file(req, fsp, NORMAL_CLOSE);
6303         if (!NT_STATUS_IS_OK(status)) {
6304                 reply_nterror(req, status);
6305         } else {
6306                 reply_outbuf(req, 0, 0);
6307         }
6308
6309         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6310
6311         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6312  out:
6313         TALLOC_FREE(smb_dname);
6314         END_PROFILE(SMBrmdir);
6315         return;
6316 }
6317
6318 /*******************************************************************
6319  Resolve wildcards in a filename rename.
6320 ********************************************************************/
6321
6322 static bool resolve_wildcards(TALLOC_CTX *ctx,
6323                                 const char *name1,
6324                                 const char *name2,
6325                                 char **pp_newname)
6326 {
6327         char *name2_copy = NULL;
6328         char *root1 = NULL;
6329         char *root2 = NULL;
6330         char *ext1 = NULL;
6331         char *ext2 = NULL;
6332         char *p,*p2, *pname1, *pname2;
6333
6334         name2_copy = talloc_strdup(ctx, name2);
6335         if (!name2_copy) {
6336                 return False;
6337         }
6338
6339         pname1 = strrchr_m(name1,'/');
6340         pname2 = strrchr_m(name2_copy,'/');
6341
6342         if (!pname1 || !pname2) {
6343                 return False;
6344         }
6345
6346         /* Truncate the copy of name2 at the last '/' */
6347         *pname2 = '\0';
6348
6349         /* Now go past the '/' */
6350         pname1++;
6351         pname2++;
6352
6353         root1 = talloc_strdup(ctx, pname1);
6354         root2 = talloc_strdup(ctx, pname2);
6355
6356         if (!root1 || !root2) {
6357                 return False;
6358         }
6359
6360         p = strrchr_m(root1,'.');
6361         if (p) {
6362                 *p = 0;
6363                 ext1 = talloc_strdup(ctx, p+1);
6364         } else {
6365                 ext1 = talloc_strdup(ctx, "");
6366         }
6367         p = strrchr_m(root2,'.');
6368         if (p) {
6369                 *p = 0;
6370                 ext2 = talloc_strdup(ctx, p+1);
6371         } else {
6372                 ext2 = talloc_strdup(ctx, "");
6373         }
6374
6375         if (!ext1 || !ext2) {
6376                 return False;
6377         }
6378
6379         p = root1;
6380         p2 = root2;
6381         while (*p2) {
6382                 if (*p2 == '?') {
6383                         /* Hmmm. Should this be mb-aware ? */
6384                         *p2 = *p;
6385                         p2++;
6386                 } else if (*p2 == '*') {
6387                         *p2 = '\0';
6388                         root2 = talloc_asprintf(ctx, "%s%s",
6389                                                 root2,
6390                                                 p);
6391                         if (!root2) {
6392                                 return False;
6393                         }
6394                         break;
6395                 } else {
6396                         p2++;
6397                 }
6398                 if (*p) {
6399                         p++;
6400                 }
6401         }
6402
6403         p = ext1;
6404         p2 = ext2;
6405         while (*p2) {
6406                 if (*p2 == '?') {
6407                         /* Hmmm. Should this be mb-aware ? */
6408                         *p2 = *p;
6409                         p2++;
6410                 } else if (*p2 == '*') {
6411                         *p2 = '\0';
6412                         ext2 = talloc_asprintf(ctx, "%s%s",
6413                                                 ext2,
6414                                                 p);
6415                         if (!ext2) {
6416                                 return False;
6417                         }
6418                         break;
6419                 } else {
6420                         p2++;
6421                 }
6422                 if (*p) {
6423                         p++;
6424                 }
6425         }
6426
6427         if (*ext2) {
6428                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6429                                 name2_copy,
6430                                 root2,
6431                                 ext2);
6432         } else {
6433                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6434                                 name2_copy,
6435                                 root2);
6436         }
6437
6438         if (!*pp_newname) {
6439                 return False;
6440         }
6441
6442         return True;
6443 }
6444
6445 /****************************************************************************
6446  Ensure open files have their names updated. Updated to notify other smbd's
6447  asynchronously.
6448 ****************************************************************************/
6449
6450 static void rename_open_files(connection_struct *conn,
6451                               struct share_mode_lock *lck,
6452                               struct file_id id,
6453                               uint32_t orig_name_hash,
6454                               const struct smb_filename *smb_fname_dst)
6455 {
6456         files_struct *fsp;
6457         bool did_rename = False;
6458         NTSTATUS status;
6459         uint32_t new_name_hash = 0;
6460
6461         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6462             fsp = file_find_di_next(fsp)) {
6463                 /* fsp_name is a relative path under the fsp. To change this for other
6464                    sharepaths we need to manipulate relative paths. */
6465                 /* TODO - create the absolute path and manipulate the newname
6466                    relative to the sharepath. */
6467                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6468                         continue;
6469                 }
6470                 if (fsp->name_hash != orig_name_hash) {
6471                         continue;
6472                 }
6473                 DEBUG(10, ("rename_open_files: renaming file %s "
6474                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6475                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6476                            smb_fname_str_dbg(smb_fname_dst)));
6477
6478                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6479                 if (NT_STATUS_IS_OK(status)) {
6480                         did_rename = True;
6481                         new_name_hash = fsp->name_hash;
6482                 }
6483         }
6484
6485         if (!did_rename) {
6486                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6487                            "for %s\n", file_id_string_tos(&id),
6488                            smb_fname_str_dbg(smb_fname_dst)));
6489         }
6490
6491         /* Send messages to all smbd's (not ourself) that the name has changed. */
6492         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6493                               orig_name_hash, new_name_hash,
6494                               smb_fname_dst);
6495
6496 }
6497
6498 /****************************************************************************
6499  We need to check if the source path is a parent directory of the destination
6500  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6501  refuse the rename with a sharing violation. Under UNIX the above call can
6502  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6503  probably need to check that the client is a Windows one before disallowing
6504  this as a UNIX client (one with UNIX extensions) can know the source is a
6505  symlink and make this decision intelligently. Found by an excellent bug
6506  report from <AndyLiebman@aol.com>.
6507 ****************************************************************************/
6508
6509 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6510                                      const struct smb_filename *smb_fname_dst)
6511 {
6512         const char *psrc = smb_fname_src->base_name;
6513         const char *pdst = smb_fname_dst->base_name;
6514         size_t slen;
6515
6516         if (psrc[0] == '.' && psrc[1] == '/') {
6517                 psrc += 2;
6518         }
6519         if (pdst[0] == '.' && pdst[1] == '/') {
6520                 pdst += 2;
6521         }
6522         if ((slen = strlen(psrc)) > strlen(pdst)) {
6523                 return False;
6524         }
6525         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6526 }
6527
6528 /*
6529  * Do the notify calls from a rename
6530  */
6531
6532 static void notify_rename(connection_struct *conn, bool is_dir,
6533                           const struct smb_filename *smb_fname_src,
6534                           const struct smb_filename *smb_fname_dst)
6535 {
6536         char *parent_dir_src = NULL;
6537         char *parent_dir_dst = NULL;
6538         uint32_t mask;
6539
6540         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6541                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6542
6543         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6544                             &parent_dir_src, NULL) ||
6545             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6546                             &parent_dir_dst, NULL)) {
6547                 goto out;
6548         }
6549
6550         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6551                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6552                              smb_fname_src->base_name);
6553                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6554                              smb_fname_dst->base_name);
6555         }
6556         else {
6557                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6558                              smb_fname_src->base_name);
6559                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6560                              smb_fname_dst->base_name);
6561         }
6562
6563         /* this is a strange one. w2k3 gives an additional event for
6564            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6565            files, but not directories */
6566         if (!is_dir) {
6567                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6568                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6569                              |FILE_NOTIFY_CHANGE_CREATION,
6570                              smb_fname_dst->base_name);
6571         }
6572  out:
6573         TALLOC_FREE(parent_dir_src);
6574         TALLOC_FREE(parent_dir_dst);
6575 }
6576
6577 /****************************************************************************
6578  Returns an error if the parent directory for a filename is open in an
6579  incompatible way.
6580 ****************************************************************************/
6581
6582 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6583                                         const struct smb_filename *smb_fname_dst_in)
6584 {
6585         char *parent_dir = NULL;
6586         struct smb_filename smb_fname_parent;
6587         struct file_id id;
6588         files_struct *fsp = NULL;
6589         int ret;
6590
6591         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6592                         &parent_dir, NULL)) {
6593                 return NT_STATUS_NO_MEMORY;
6594         }
6595         ZERO_STRUCT(smb_fname_parent);
6596         smb_fname_parent.base_name = parent_dir;
6597
6598         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6599         if (ret == -1) {
6600                 return map_nt_error_from_unix(errno);
6601         }
6602
6603         /*
6604          * We're only checking on this smbd here, mostly good
6605          * enough.. and will pass tests.
6606          */
6607
6608         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6609         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6610                         fsp = file_find_di_next(fsp)) {
6611                 if (fsp->access_mask & DELETE_ACCESS) {
6612                         return NT_STATUS_SHARING_VIOLATION;
6613                 }
6614         }
6615         return NT_STATUS_OK;
6616 }
6617
6618 /****************************************************************************
6619  Rename an open file - given an fsp.
6620 ****************************************************************************/
6621
6622 NTSTATUS rename_internals_fsp(connection_struct *conn,
6623                         files_struct *fsp,
6624                         const struct smb_filename *smb_fname_dst_in,
6625                         uint32_t attrs,
6626                         bool replace_if_exists)
6627 {
6628         TALLOC_CTX *ctx = talloc_tos();
6629         struct smb_filename *smb_fname_dst = NULL;
6630         NTSTATUS status = NT_STATUS_OK;
6631         struct share_mode_lock *lck = NULL;
6632         uint32_t access_mask = SEC_DIR_ADD_FILE;
6633         bool dst_exists, old_is_stream, new_is_stream;
6634
6635         status = check_name(conn, smb_fname_dst_in);
6636         if (!NT_STATUS_IS_OK(status)) {
6637                 return status;
6638         }
6639
6640         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6641         if (!NT_STATUS_IS_OK(status)) {
6642                 return status;
6643         }
6644
6645         /* Make a copy of the dst smb_fname structs */
6646
6647         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6648         if (smb_fname_dst == NULL) {
6649                 status = NT_STATUS_NO_MEMORY;
6650                 goto out;
6651         }
6652
6653         /*
6654          * Check for special case with case preserving and not
6655          * case sensitive. If the new last component differs from the original
6656          * last component only by case, then we should allow
6657          * the rename (user is trying to change the case of the
6658          * filename).
6659          */
6660         if (!conn->case_sensitive && conn->case_preserve &&
6661             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6662             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6663                 char *fname_dst_parent = NULL;
6664                 const char *fname_dst_lcomp = NULL;
6665                 char *orig_lcomp_path = NULL;
6666                 char *orig_lcomp_stream = NULL;
6667                 bool ok = true;
6668
6669                 /*
6670                  * Split off the last component of the processed
6671                  * destination name. We will compare this to
6672                  * the split components of smb_fname_dst->original_lcomp.
6673                  */
6674                 if (!parent_dirname(ctx,
6675                                 smb_fname_dst->base_name,
6676                                 &fname_dst_parent,
6677                                 &fname_dst_lcomp)) {
6678                         status = NT_STATUS_NO_MEMORY;
6679                         goto out;
6680                 }
6681
6682                 /*
6683                  * The original_lcomp component contains
6684                  * the last_component of the path + stream
6685                  * name (if a stream exists).
6686                  *
6687                  * Split off the stream name so we
6688                  * can check them separately.
6689                  */
6690
6691                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6692                         /* POSIX - no stream component. */
6693                         orig_lcomp_path = talloc_strdup(ctx,
6694                                                 smb_fname_dst->original_lcomp);
6695                         if (orig_lcomp_path == NULL) {
6696                                 ok = false;
6697                         }
6698                 } else {
6699                         ok = split_stream_filename(ctx,
6700                                         smb_fname_dst->original_lcomp,
6701                                         &orig_lcomp_path,
6702                                         &orig_lcomp_stream);
6703                 }
6704
6705                 if (!ok) {
6706                         TALLOC_FREE(fname_dst_parent);
6707                         status = NT_STATUS_NO_MEMORY;
6708                         goto out;
6709                 }
6710
6711                 /* If the base names only differ by case, use original. */
6712                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6713                         char *tmp;
6714                         /*
6715                          * Replace the modified last component with the
6716                          * original.
6717                          */
6718                         if (!ISDOT(fname_dst_parent)) {
6719                                 tmp = talloc_asprintf(smb_fname_dst,
6720                                         "%s/%s",
6721                                         fname_dst_parent,
6722                                         orig_lcomp_path);
6723                         } else {
6724                                 tmp = talloc_strdup(smb_fname_dst,
6725                                         orig_lcomp_path);
6726                         }
6727                         if (tmp == NULL) {
6728                                 status = NT_STATUS_NO_MEMORY;
6729                                 TALLOC_FREE(fname_dst_parent);
6730                                 TALLOC_FREE(orig_lcomp_path);
6731                                 TALLOC_FREE(orig_lcomp_stream);
6732                                 goto out;
6733                         }
6734                         TALLOC_FREE(smb_fname_dst->base_name);
6735                         smb_fname_dst->base_name = tmp;
6736                 }
6737
6738                 /* If the stream_names only differ by case, use original. */
6739                 if(!strcsequal(smb_fname_dst->stream_name,
6740                                orig_lcomp_stream)) {
6741                         /* Use the original stream. */
6742                         char *tmp = talloc_strdup(smb_fname_dst,
6743                                             orig_lcomp_stream);
6744                         if (tmp == NULL) {
6745                                 status = NT_STATUS_NO_MEMORY;
6746                                 TALLOC_FREE(fname_dst_parent);
6747                                 TALLOC_FREE(orig_lcomp_path);
6748                                 TALLOC_FREE(orig_lcomp_stream);
6749                                 goto out;
6750                         }
6751                         TALLOC_FREE(smb_fname_dst->stream_name);
6752                         smb_fname_dst->stream_name = tmp;
6753                 }
6754                 TALLOC_FREE(fname_dst_parent);
6755                 TALLOC_FREE(orig_lcomp_path);
6756                 TALLOC_FREE(orig_lcomp_stream);
6757         }
6758
6759         /*
6760          * If the src and dest names are identical - including case,
6761          * don't do the rename, just return success.
6762          */
6763
6764         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6765             strcsequal(fsp->fsp_name->stream_name,
6766                        smb_fname_dst->stream_name)) {
6767                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6768                           "- returning success\n",
6769                           smb_fname_str_dbg(smb_fname_dst)));
6770                 status = NT_STATUS_OK;
6771                 goto out;
6772         }
6773
6774         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6775         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6776
6777         /* Return the correct error code if both names aren't streams. */
6778         if (!old_is_stream && new_is_stream) {
6779                 status = NT_STATUS_OBJECT_NAME_INVALID;
6780                 goto out;
6781         }
6782
6783         if (old_is_stream && !new_is_stream) {
6784                 status = NT_STATUS_INVALID_PARAMETER;
6785                 goto out;
6786         }
6787
6788         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6789
6790         if(!replace_if_exists && dst_exists) {
6791                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6792                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6793                           smb_fname_str_dbg(smb_fname_dst)));
6794                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6795                 goto out;
6796         }
6797
6798         if (dst_exists) {
6799                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6800                     &smb_fname_dst->st);
6801                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6802                                                            fileid);
6803                 /* The file can be open when renaming a stream */
6804                 if (dst_fsp && !new_is_stream) {
6805                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6806                         status = NT_STATUS_ACCESS_DENIED;
6807                         goto out;
6808                 }
6809         }
6810
6811         /* Ensure we have a valid stat struct for the source. */
6812         status = vfs_stat_fsp(fsp);
6813         if (!NT_STATUS_IS_OK(status)) {
6814                 goto out;
6815         }
6816
6817         status = can_rename(conn, fsp, attrs);
6818
6819         if (!NT_STATUS_IS_OK(status)) {
6820                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6821                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6822                           smb_fname_str_dbg(smb_fname_dst)));
6823                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6824                         status = NT_STATUS_ACCESS_DENIED;
6825                 goto out;
6826         }
6827
6828         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6829                 status = NT_STATUS_ACCESS_DENIED;
6830                 goto out;
6831         }
6832
6833         /* Do we have rights to move into the destination ? */
6834         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6835                 /* We're moving a directory. */
6836                 access_mask = SEC_DIR_ADD_SUBDIR;
6837         }
6838         status = check_parent_access(conn,
6839                                 smb_fname_dst,
6840                                 access_mask);
6841         if (!NT_STATUS_IS_OK(status)) {
6842                 DBG_INFO("check_parent_access on "
6843                         "dst %s returned %s\n",
6844                         smb_fname_str_dbg(smb_fname_dst),
6845                         nt_errstr(status));
6846                 goto out;
6847         }
6848
6849         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6850
6851         /*
6852          * We have the file open ourselves, so not being able to get the
6853          * corresponding share mode lock is a fatal error.
6854          */
6855
6856         SMB_ASSERT(lck != NULL);
6857
6858         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6859                 uint32_t create_options = fsp->fh->private_options;
6860
6861                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6862                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6863                           smb_fname_str_dbg(smb_fname_dst)));
6864
6865                 if (!fsp->is_directory &&
6866                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6867                     (lp_map_archive(SNUM(conn)) ||
6868                     lp_store_dos_attributes(SNUM(conn)))) {
6869                         /* We must set the archive bit on the newly
6870                            renamed file. */
6871                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6872                                 uint32_t old_dosmode = dos_mode(conn,
6873                                                         smb_fname_dst);
6874                                 file_set_dosmode(conn,
6875                                         smb_fname_dst,
6876                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6877                                         NULL,
6878                                         true);
6879                         }
6880                 }
6881
6882                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6883                               smb_fname_dst);
6884
6885                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6886                                   smb_fname_dst);
6887
6888                 /*
6889                  * A rename acts as a new file create w.r.t. allowing an initial delete
6890                  * on close, probably because in Windows there is a new handle to the
6891                  * new file. If initial delete on close was requested but not
6892                  * originally set, we need to set it here. This is probably not 100% correct,
6893                  * but will work for the CIFSFS client which in non-posix mode
6894                  * depends on these semantics. JRA.
6895                  */
6896
6897                 if (create_options & FILE_DELETE_ON_CLOSE) {
6898                         status = can_set_delete_on_close(fsp, 0);
6899
6900                         if (NT_STATUS_IS_OK(status)) {
6901                                 /* Note that here we set the *inital* delete on close flag,
6902                                  * not the regular one. The magic gets handled in close. */
6903                                 fsp->initial_delete_on_close = True;
6904                         }
6905                 }
6906                 TALLOC_FREE(lck);
6907                 status = NT_STATUS_OK;
6908                 goto out;
6909         }
6910
6911         TALLOC_FREE(lck);
6912
6913         if (errno == ENOTDIR || errno == EISDIR) {
6914                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6915         } else {
6916                 status = map_nt_error_from_unix(errno);
6917         }
6918
6919         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6920                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6921                   smb_fname_str_dbg(smb_fname_dst)));
6922
6923  out:
6924         TALLOC_FREE(smb_fname_dst);
6925
6926         return status;
6927 }
6928
6929 /****************************************************************************
6930  The guts of the rename command, split out so it may be called by the NT SMB
6931  code.
6932 ****************************************************************************/
6933
6934 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6935                         connection_struct *conn,
6936                         struct smb_request *req,
6937                         struct smb_filename *smb_fname_src,
6938                         struct smb_filename *smb_fname_dst,
6939                         uint32_t attrs,
6940                         bool replace_if_exists,
6941                         bool src_has_wild,
6942                         bool dest_has_wild,
6943                         uint32_t access_mask)
6944 {
6945         char *fname_src_dir = NULL;
6946         struct smb_filename *smb_fname_src_dir = NULL;
6947         char *fname_src_mask = NULL;
6948         int count=0;
6949         NTSTATUS status = NT_STATUS_OK;
6950         struct smb_Dir *dir_hnd = NULL;
6951         const char *dname = NULL;
6952         char *talloced = NULL;
6953         long offset = 0;
6954         int create_options = 0;
6955         bool posix_pathnames = (req != NULL && req->posix_pathnames);
6956         int rc;
6957
6958         /*
6959          * Split the old name into directory and last component
6960          * strings. Note that unix_convert may have stripped off a
6961          * leading ./ from both name and newname if the rename is
6962          * at the root of the share. We need to make sure either both
6963          * name and newname contain a / character or neither of them do
6964          * as this is checked in resolve_wildcards().
6965          */
6966
6967         /* Split up the directory from the filename/mask. */
6968         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6969                                       &fname_src_dir, &fname_src_mask);
6970         if (!NT_STATUS_IS_OK(status)) {
6971                 status = NT_STATUS_NO_MEMORY;
6972                 goto out;
6973         }
6974
6975         /*
6976          * We should only check the mangled cache
6977          * here if unix_convert failed. This means
6978          * that the path in 'mask' doesn't exist
6979          * on the file system and so we need to look
6980          * for a possible mangle. This patch from
6981          * Tine Smukavec <valentin.smukavec@hermes.si>.
6982          */
6983
6984         if (!VALID_STAT(smb_fname_src->st) &&
6985             mangle_is_mangled(fname_src_mask, conn->params)) {
6986                 char *new_mask = NULL;
6987                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6988                                             conn->params);
6989                 if (new_mask) {
6990                         TALLOC_FREE(fname_src_mask);
6991                         fname_src_mask = new_mask;
6992                 }
6993         }
6994
6995         if (!src_has_wild) {
6996                 files_struct *fsp;
6997
6998                 /*
6999                  * Only one file needs to be renamed. Append the mask back
7000                  * onto the directory.
7001                  */
7002                 TALLOC_FREE(smb_fname_src->base_name);
7003                 if (ISDOT(fname_src_dir)) {
7004                         /* Ensure we use canonical names on open. */
7005                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7006                                                         "%s",
7007                                                         fname_src_mask);
7008                 } else {
7009                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7010                                                         "%s/%s",
7011                                                         fname_src_dir,
7012                                                         fname_src_mask);
7013                 }
7014                 if (!smb_fname_src->base_name) {
7015                         status = NT_STATUS_NO_MEMORY;
7016                         goto out;
7017                 }
7018
7019                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7020                           "case_preserve = %d, short case preserve = %d, "
7021                           "directory = %s, newname = %s, "
7022                           "last_component_dest = %s\n",
7023                           conn->case_sensitive, conn->case_preserve,
7024                           conn->short_case_preserve,
7025                           smb_fname_str_dbg(smb_fname_src),
7026                           smb_fname_str_dbg(smb_fname_dst),
7027                           smb_fname_dst->original_lcomp));
7028
7029                 /* The dest name still may have wildcards. */
7030                 if (dest_has_wild) {
7031                         char *fname_dst_mod = NULL;
7032                         if (!resolve_wildcards(smb_fname_dst,
7033                                                smb_fname_src->base_name,
7034                                                smb_fname_dst->base_name,
7035                                                &fname_dst_mod)) {
7036                                 DEBUG(6, ("rename_internals: resolve_wildcards "
7037                                           "%s %s failed\n",
7038                                           smb_fname_src->base_name,
7039                                           smb_fname_dst->base_name));
7040                                 status = NT_STATUS_NO_MEMORY;
7041                                 goto out;
7042                         }
7043                         TALLOC_FREE(smb_fname_dst->base_name);
7044                         smb_fname_dst->base_name = fname_dst_mod;
7045                 }
7046
7047                 ZERO_STRUCT(smb_fname_src->st);
7048                 if (posix_pathnames) {
7049                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7050                 } else {
7051                         rc = SMB_VFS_STAT(conn, smb_fname_src);
7052                 }
7053                 if (rc == -1) {
7054                         status = map_nt_error_from_unix_common(errno);
7055                         goto out;
7056                 }
7057
7058                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7059                         create_options |= FILE_DIRECTORY_FILE;
7060                 }
7061
7062                 status = SMB_VFS_CREATE_FILE(
7063                         conn,                           /* conn */
7064                         req,                            /* req */
7065                         0,                              /* root_dir_fid */
7066                         smb_fname_src,                  /* fname */
7067                         access_mask,                    /* access_mask */
7068                         (FILE_SHARE_READ |              /* share_access */
7069                             FILE_SHARE_WRITE),
7070                         FILE_OPEN,                      /* create_disposition*/
7071                         create_options,                 /* create_options */
7072                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7073                         0,                              /* oplock_request */
7074                         NULL,                           /* lease */
7075                         0,                              /* allocation_size */
7076                         0,                              /* private_flags */
7077                         NULL,                           /* sd */
7078                         NULL,                           /* ea_list */
7079                         &fsp,                           /* result */
7080                         NULL,                           /* pinfo */
7081                         NULL, NULL);                    /* create context */
7082
7083                 if (!NT_STATUS_IS_OK(status)) {
7084                         DEBUG(3, ("Could not open rename source %s: %s\n",
7085                                   smb_fname_str_dbg(smb_fname_src),
7086                                   nt_errstr(status)));
7087                         goto out;
7088                 }
7089
7090                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7091                                               attrs, replace_if_exists);
7092
7093                 close_file(req, fsp, NORMAL_CLOSE);
7094
7095                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7096                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7097                           smb_fname_str_dbg(smb_fname_dst)));
7098
7099                 goto out;
7100         }
7101
7102         /*
7103          * Wildcards - process each file that matches.
7104          */
7105         if (strequal(fname_src_mask, "????????.???")) {
7106                 TALLOC_FREE(fname_src_mask);
7107                 fname_src_mask = talloc_strdup(ctx, "*");
7108                 if (!fname_src_mask) {
7109                         status = NT_STATUS_NO_MEMORY;
7110                         goto out;
7111                 }
7112         }
7113
7114         smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7115                                 fname_src_dir,
7116                                 NULL,
7117                                 NULL,
7118                                 smb_fname_src->flags);
7119         if (smb_fname_src_dir == NULL) {
7120                 status = NT_STATUS_NO_MEMORY;
7121                 goto out;
7122         }
7123
7124         status = check_name(conn, smb_fname_src_dir);
7125         if (!NT_STATUS_IS_OK(status)) {
7126                 goto out;
7127         }
7128
7129         dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7130                           attrs);
7131         if (dir_hnd == NULL) {
7132                 status = map_nt_error_from_unix(errno);
7133                 goto out;
7134         }
7135
7136         status = NT_STATUS_NO_SUCH_FILE;
7137         /*
7138          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7139          * - gentest fix. JRA
7140          */
7141
7142         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7143                                     &talloced))) {
7144                 files_struct *fsp = NULL;
7145                 char *destname = NULL;
7146                 bool sysdir_entry = False;
7147
7148                 /* Quick check for "." and ".." */
7149                 if (ISDOT(dname) || ISDOTDOT(dname)) {
7150                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7151                                 sysdir_entry = True;
7152                         } else {
7153                                 TALLOC_FREE(talloced);
7154                                 continue;
7155                         }
7156                 }
7157
7158                 if (!is_visible_file(conn, fname_src_dir, dname,
7159                                      &smb_fname_src->st, false)) {
7160                         TALLOC_FREE(talloced);
7161                         continue;
7162                 }
7163
7164                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7165                         TALLOC_FREE(talloced);
7166                         continue;
7167                 }
7168
7169                 if (sysdir_entry) {
7170                         status = NT_STATUS_OBJECT_NAME_INVALID;
7171                         break;
7172                 }
7173
7174                 TALLOC_FREE(smb_fname_src->base_name);
7175                 if (ISDOT(fname_src_dir)) {
7176                         /* Ensure we use canonical names on open. */
7177                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7178                                                         "%s",
7179                                                         dname);
7180                 } else {
7181                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7182                                                         "%s/%s",
7183                                                         fname_src_dir,
7184                                                         dname);
7185                 }
7186                 if (!smb_fname_src->base_name) {
7187                         status = NT_STATUS_NO_MEMORY;
7188                         goto out;
7189                 }
7190
7191                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7192                                        smb_fname_dst->base_name,
7193                                        &destname)) {
7194                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
7195                                   smb_fname_src->base_name, destname));
7196                         TALLOC_FREE(talloced);
7197                         continue;
7198                 }
7199                 if (!destname) {
7200                         status = NT_STATUS_NO_MEMORY;
7201                         goto out;
7202                 }
7203
7204                 TALLOC_FREE(smb_fname_dst->base_name);
7205                 smb_fname_dst->base_name = destname;
7206
7207                 ZERO_STRUCT(smb_fname_src->st);
7208                 if (posix_pathnames) {
7209                         SMB_VFS_LSTAT(conn, smb_fname_src);
7210                 } else {
7211                         SMB_VFS_STAT(conn, smb_fname_src);
7212                 }
7213
7214                 create_options = 0;
7215
7216                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7217                         create_options |= FILE_DIRECTORY_FILE;
7218                 }
7219
7220                 status = SMB_VFS_CREATE_FILE(
7221                         conn,                           /* conn */
7222                         req,                            /* req */
7223                         0,                              /* root_dir_fid */
7224                         smb_fname_src,                  /* fname */
7225                         access_mask,                    /* access_mask */
7226                         (FILE_SHARE_READ |              /* share_access */
7227                             FILE_SHARE_WRITE),
7228                         FILE_OPEN,                      /* create_disposition*/
7229                         create_options,                 /* create_options */
7230                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7231                         0,                              /* oplock_request */
7232                         NULL,                           /* lease */
7233                         0,                              /* allocation_size */
7234                         0,                              /* private_flags */
7235                         NULL,                           /* sd */
7236                         NULL,                           /* ea_list */
7237                         &fsp,                           /* result */
7238                         NULL,                           /* pinfo */
7239                         NULL, NULL);                    /* create context */
7240
7241                 if (!NT_STATUS_IS_OK(status)) {
7242                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7243                                  "returned %s rename %s -> %s\n",
7244                                  nt_errstr(status),
7245                                  smb_fname_str_dbg(smb_fname_src),
7246                                  smb_fname_str_dbg(smb_fname_dst)));
7247                         break;
7248                 }
7249
7250                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7251                                                               dname);
7252                 if (!smb_fname_dst->original_lcomp) {
7253                         status = NT_STATUS_NO_MEMORY;
7254                         goto out;
7255                 }
7256
7257                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7258                                               attrs, replace_if_exists);
7259
7260                 close_file(req, fsp, NORMAL_CLOSE);
7261
7262                 if (!NT_STATUS_IS_OK(status)) {
7263                         DEBUG(3, ("rename_internals_fsp returned %s for "
7264                                   "rename %s -> %s\n", nt_errstr(status),
7265                                   smb_fname_str_dbg(smb_fname_src),
7266                                   smb_fname_str_dbg(smb_fname_dst)));
7267                         break;
7268                 }
7269
7270                 count++;
7271
7272                 DEBUG(3,("rename_internals: doing rename on %s -> "
7273                          "%s\n", smb_fname_str_dbg(smb_fname_src),
7274                          smb_fname_str_dbg(smb_fname_src)));
7275                 TALLOC_FREE(talloced);
7276         }
7277         TALLOC_FREE(dir_hnd);
7278
7279         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7280                 status = map_nt_error_from_unix(errno);
7281         }
7282
7283  out:
7284         TALLOC_FREE(talloced);
7285         TALLOC_FREE(smb_fname_src_dir);
7286         TALLOC_FREE(fname_src_dir);
7287         TALLOC_FREE(fname_src_mask);
7288         return status;
7289 }
7290
7291 /****************************************************************************
7292  Reply to a mv.
7293 ****************************************************************************/
7294
7295 void reply_mv(struct smb_request *req)
7296 {
7297         connection_struct *conn = req->conn;
7298         char *name = NULL;
7299         char *newname = NULL;
7300         const char *p;
7301         uint32_t attrs;
7302         NTSTATUS status;
7303         bool src_has_wcard = False;
7304         bool dest_has_wcard = False;
7305         TALLOC_CTX *ctx = talloc_tos();
7306         struct smb_filename *smb_fname_src = NULL;
7307         struct smb_filename *smb_fname_dst = NULL;
7308         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7309                 (req->posix_pathnames ?
7310                         UCF_UNIX_NAME_LOOKUP :
7311                         UCF_COND_ALLOW_WCARD_LCOMP);
7312         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7313                 UCF_SAVE_LCOMP |
7314                 (req->posix_pathnames ?
7315                         0 :
7316                         UCF_COND_ALLOW_WCARD_LCOMP);
7317         bool stream_rename = false;
7318
7319         START_PROFILE(SMBmv);
7320
7321         if (req->wct < 1) {
7322                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7323                 goto out;
7324         }
7325
7326         attrs = SVAL(req->vwv+0, 0);
7327
7328         p = (const char *)req->buf + 1;
7329         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7330                                        &status, &src_has_wcard);
7331         if (!NT_STATUS_IS_OK(status)) {
7332                 reply_nterror(req, status);
7333                 goto out;
7334         }
7335         p++;
7336         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7337                                        &status, &dest_has_wcard);
7338         if (!NT_STATUS_IS_OK(status)) {
7339                 reply_nterror(req, status);
7340                 goto out;
7341         }
7342
7343         if (!req->posix_pathnames) {
7344                 /* The newname must begin with a ':' if the
7345                    name contains a ':'. */
7346                 if (strchr_m(name, ':')) {
7347                         if (newname[0] != ':') {
7348                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7349                                 goto out;
7350                         }
7351                         stream_rename = true;
7352                 }
7353         }
7354
7355         status = filename_convert(ctx,
7356                                   conn,
7357                                   name,
7358                                   src_ucf_flags,
7359                                   &src_has_wcard,
7360                                   &smb_fname_src);
7361
7362         if (!NT_STATUS_IS_OK(status)) {
7363                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7364                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7365                                         ERRSRV, ERRbadpath);
7366                         goto out;
7367                 }
7368                 reply_nterror(req, status);
7369                 goto out;
7370         }
7371
7372         status = filename_convert(ctx,
7373                                   conn,
7374                                   newname,
7375                                   dst_ucf_flags,
7376                                   &dest_has_wcard,
7377                                   &smb_fname_dst);
7378
7379         if (!NT_STATUS_IS_OK(status)) {
7380                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7381                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7382                                         ERRSRV, ERRbadpath);
7383                         goto out;
7384                 }
7385                 reply_nterror(req, status);
7386                 goto out;
7387         }
7388
7389         if (stream_rename) {
7390                 /* smb_fname_dst->base_name must be the same as
7391                    smb_fname_src->base_name. */
7392                 TALLOC_FREE(smb_fname_dst->base_name);
7393                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7394                                                 smb_fname_src->base_name);
7395                 if (!smb_fname_dst->base_name) {
7396                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7397                         goto out;
7398                 }
7399         }
7400
7401         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7402                  smb_fname_str_dbg(smb_fname_dst)));
7403
7404         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7405                                   attrs, False, src_has_wcard, dest_has_wcard,
7406                                   DELETE_ACCESS);
7407         if (!NT_STATUS_IS_OK(status)) {
7408                 if (open_was_deferred(req->xconn, req->mid)) {
7409                         /* We have re-scheduled this call. */
7410                         goto out;
7411                 }
7412                 reply_nterror(req, status);
7413                 goto out;
7414         }
7415
7416         reply_outbuf(req, 0, 0);
7417  out:
7418         TALLOC_FREE(smb_fname_src);
7419         TALLOC_FREE(smb_fname_dst);
7420         END_PROFILE(SMBmv);
7421         return;
7422 }
7423
7424 /*******************************************************************
7425  Copy a file as part of a reply_copy.
7426 ******************************************************************/
7427
7428 /*
7429  * TODO: check error codes on all callers
7430  */
7431
7432 NTSTATUS copy_file(TALLOC_CTX *ctx,
7433                         connection_struct *conn,
7434                         struct smb_filename *smb_fname_src,
7435                         struct smb_filename *smb_fname_dst,
7436                         int ofun,
7437                         int count,
7438                         bool target_is_directory)
7439 {
7440         struct smb_filename *smb_fname_dst_tmp = NULL;
7441         off_t ret=-1;
7442         files_struct *fsp1,*fsp2;
7443         uint32_t dosattrs;
7444         uint32_t new_create_disposition;
7445         NTSTATUS status;
7446
7447
7448         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7449         if (smb_fname_dst_tmp == NULL) {
7450                 return NT_STATUS_NO_MEMORY;
7451         }
7452
7453         /*
7454          * If the target is a directory, extract the last component from the
7455          * src filename and append it to the dst filename
7456          */
7457         if (target_is_directory) {
7458                 const char *p;
7459
7460                 /* dest/target can't be a stream if it's a directory. */
7461                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7462
7463                 p = strrchr_m(smb_fname_src->base_name,'/');
7464                 if (p) {
7465                         p++;
7466                 } else {
7467                         p = smb_fname_src->base_name;
7468                 }
7469                 smb_fname_dst_tmp->base_name =
7470                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7471                                            p);
7472                 if (!smb_fname_dst_tmp->base_name) {
7473                         status = NT_STATUS_NO_MEMORY;
7474                         goto out;
7475                 }
7476         }
7477
7478         status = vfs_file_exist(conn, smb_fname_src);
7479         if (!NT_STATUS_IS_OK(status)) {
7480                 goto out;
7481         }
7482
7483         if (!target_is_directory && count) {
7484                 new_create_disposition = FILE_OPEN;
7485         } else {
7486                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7487                                                  0, ofun,
7488                                                  NULL, NULL,
7489                                                  &new_create_disposition,
7490                                                  NULL,
7491                                                  NULL)) {
7492                         status = NT_STATUS_INVALID_PARAMETER;
7493                         goto out;
7494                 }
7495         }
7496
7497         /* Open the src file for reading. */
7498         status = SMB_VFS_CREATE_FILE(
7499                 conn,                                   /* conn */
7500                 NULL,                                   /* req */
7501                 0,                                      /* root_dir_fid */
7502                 smb_fname_src,                          /* fname */
7503                 FILE_GENERIC_READ,                      /* access_mask */
7504                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7505                 FILE_OPEN,                              /* create_disposition*/
7506                 0,                                      /* create_options */
7507                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7508                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7509                 NULL,                                   /* lease */
7510                 0,                                      /* allocation_size */
7511                 0,                                      /* private_flags */
7512                 NULL,                                   /* sd */
7513                 NULL,                                   /* ea_list */
7514                 &fsp1,                                  /* result */
7515                 NULL,                                   /* psbuf */
7516                 NULL, NULL);                            /* create context */
7517
7518         if (!NT_STATUS_IS_OK(status)) {
7519                 goto out;
7520         }
7521
7522         dosattrs = dos_mode(conn, smb_fname_src);
7523
7524         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7525                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7526         }
7527
7528         /* Open the dst file for writing. */
7529         status = SMB_VFS_CREATE_FILE(
7530                 conn,                                   /* conn */
7531                 NULL,                                   /* req */
7532                 0,                                      /* root_dir_fid */
7533                 smb_fname_dst,                          /* fname */
7534                 FILE_GENERIC_WRITE,                     /* access_mask */
7535                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7536                 new_create_disposition,                 /* create_disposition*/
7537                 0,                                      /* create_options */
7538                 dosattrs,                               /* file_attributes */
7539                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7540                 NULL,                                   /* lease */
7541                 0,                                      /* allocation_size */
7542                 0,                                      /* private_flags */
7543                 NULL,                                   /* sd */
7544                 NULL,                                   /* ea_list */
7545                 &fsp2,                                  /* result */
7546                 NULL,                                   /* psbuf */
7547                 NULL, NULL);                            /* create context */
7548
7549         if (!NT_STATUS_IS_OK(status)) {
7550                 close_file(NULL, fsp1, ERROR_CLOSE);
7551                 goto out;
7552         }
7553
7554         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7555                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7556                 if (ret == -1) {
7557                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7558                                 strerror(errno)));
7559                         status = map_nt_error_from_unix(errno);
7560                         close_file(NULL, fsp1, ERROR_CLOSE);
7561                         close_file(NULL, fsp2, ERROR_CLOSE);
7562                         goto out;
7563                 }
7564         }
7565
7566         /* Do the actual copy. */
7567         if (smb_fname_src->st.st_ex_size) {
7568                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7569         } else {
7570                 ret = 0;
7571         }
7572
7573         close_file(NULL, fsp1, NORMAL_CLOSE);
7574
7575         /* Ensure the modtime is set correctly on the destination file. */
7576         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7577
7578         /*
7579          * As we are opening fsp1 read-only we only expect
7580          * an error on close on fsp2 if we are out of space.
7581          * Thus we don't look at the error return from the
7582          * close of fsp1.
7583          */
7584         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7585
7586         if (!NT_STATUS_IS_OK(status)) {
7587                 goto out;
7588         }
7589
7590         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7591                 status = NT_STATUS_DISK_FULL;
7592                 goto out;
7593         }
7594
7595         status = NT_STATUS_OK;
7596
7597  out:
7598         TALLOC_FREE(smb_fname_dst_tmp);
7599         return status;
7600 }
7601
7602 /****************************************************************************
7603  Reply to a file copy.
7604 ****************************************************************************/
7605
7606 void reply_copy(struct smb_request *req)
7607 {
7608         connection_struct *conn = req->conn;
7609         struct smb_filename *smb_fname_src = NULL;
7610         struct smb_filename *smb_fname_src_dir = NULL;
7611         struct smb_filename *smb_fname_dst = NULL;
7612         char *fname_src = NULL;
7613         char *fname_dst = NULL;
7614         char *fname_src_mask = NULL;
7615         char *fname_src_dir = NULL;
7616         const char *p;
7617         int count=0;
7618         int error = ERRnoaccess;
7619         int tid2;
7620         int ofun;
7621         int flags;
7622         bool target_is_directory=False;
7623         bool source_has_wild = False;
7624         bool dest_has_wild = False;
7625         NTSTATUS status;
7626         uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7627                 ucf_flags_from_smb_request(req);
7628         uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7629                 ucf_flags_from_smb_request(req);
7630         TALLOC_CTX *ctx = talloc_tos();
7631
7632         START_PROFILE(SMBcopy);
7633
7634         if (req->wct < 3) {
7635                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636                 goto out;
7637         }
7638
7639         tid2 = SVAL(req->vwv+0, 0);
7640         ofun = SVAL(req->vwv+1, 0);
7641         flags = SVAL(req->vwv+2, 0);
7642
7643         p = (const char *)req->buf;
7644         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7645                                        &status, &source_has_wild);
7646         if (!NT_STATUS_IS_OK(status)) {
7647                 reply_nterror(req, status);
7648                 goto out;
7649         }
7650         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7651                                        &status, &dest_has_wild);
7652         if (!NT_STATUS_IS_OK(status)) {
7653                 reply_nterror(req, status);
7654                 goto out;
7655         }
7656
7657         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7658
7659         if (tid2 != conn->cnum) {
7660                 /* can't currently handle inter share copies XXXX */
7661                 DEBUG(3,("Rejecting inter-share copy\n"));
7662                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7663                 goto out;
7664         }
7665
7666         status = filename_convert(ctx, conn,
7667                                   fname_src,
7668                                   ucf_flags_src,
7669                                   &source_has_wild,
7670                                   &smb_fname_src);
7671         if (!NT_STATUS_IS_OK(status)) {
7672                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7673                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7674                                         ERRSRV, ERRbadpath);
7675                         goto out;
7676                 }
7677                 reply_nterror(req, status);
7678                 goto out;
7679         }
7680
7681         status = filename_convert(ctx, conn,
7682                                   fname_dst,
7683                                   ucf_flags_dst,
7684                                   &dest_has_wild,
7685                                   &smb_fname_dst);
7686         if (!NT_STATUS_IS_OK(status)) {
7687                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7688                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7689                                         ERRSRV, ERRbadpath);
7690                         goto out;
7691                 }
7692                 reply_nterror(req, status);
7693                 goto out;
7694         }
7695
7696         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7697
7698         if ((flags&1) && target_is_directory) {
7699                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7700                 goto out;
7701         }
7702
7703         if ((flags&2) && !target_is_directory) {
7704                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7705                 goto out;
7706         }
7707
7708         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7709                 /* wants a tree copy! XXXX */
7710                 DEBUG(3,("Rejecting tree copy\n"));
7711                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7712                 goto out;
7713         }
7714
7715         /* Split up the directory from the filename/mask. */
7716         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7717                                       &fname_src_dir, &fname_src_mask);
7718         if (!NT_STATUS_IS_OK(status)) {
7719                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720                 goto out;
7721         }
7722
7723         /*
7724          * We should only check the mangled cache
7725          * here if unix_convert failed. This means
7726          * that the path in 'mask' doesn't exist
7727          * on the file system and so we need to look
7728          * for a possible mangle. This patch from
7729          * Tine Smukavec <valentin.smukavec@hermes.si>.
7730          */
7731         if (!VALID_STAT(smb_fname_src->st) &&
7732             mangle_is_mangled(fname_src_mask, conn->params)) {
7733                 char *new_mask = NULL;
7734                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7735                                             &new_mask, conn->params);
7736
7737                 /* Use demangled name if one was successfully found. */
7738                 if (new_mask) {
7739                         TALLOC_FREE(fname_src_mask);
7740                         fname_src_mask = new_mask;
7741                 }
7742         }
7743
7744         if (!source_has_wild) {
7745
7746                 /*
7747                  * Only one file needs to be copied. Append the mask back onto
7748                  * the directory.
7749                  */
7750                 TALLOC_FREE(smb_fname_src->base_name);
7751                 if (ISDOT(fname_src_dir)) {
7752                         /* Ensure we use canonical names on open. */
7753                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7754                                                         "%s",
7755                                                         fname_src_mask);
7756                 } else {
7757                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7758                                                         "%s/%s",
7759                                                         fname_src_dir,
7760                                                         fname_src_mask);
7761                 }
7762                 if (!smb_fname_src->base_name) {
7763                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7764                         goto out;
7765                 }
7766
7767                 if (dest_has_wild) {
7768                         char *fname_dst_mod = NULL;
7769                         if (!resolve_wildcards(smb_fname_dst,
7770                                                smb_fname_src->base_name,
7771                                                smb_fname_dst->base_name,
7772                                                &fname_dst_mod)) {
7773                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7774                                 goto out;
7775                         }
7776                         TALLOC_FREE(smb_fname_dst->base_name);
7777                         smb_fname_dst->base_name = fname_dst_mod;
7778                 }
7779
7780                 status = check_name(conn, smb_fname_src);
7781                 if (!NT_STATUS_IS_OK(status)) {
7782                         reply_nterror(req, status);
7783                         goto out;
7784                 }
7785
7786                 status = check_name(conn, smb_fname_dst);
7787                 if (!NT_STATUS_IS_OK(status)) {
7788                         reply_nterror(req, status);
7789                         goto out;
7790                 }
7791
7792                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7793                                    ofun, count, target_is_directory);
7794
7795                 if(!NT_STATUS_IS_OK(status)) {
7796                         reply_nterror(req, status);
7797                         goto out;
7798                 } else {
7799                         count++;
7800                 }
7801         } else {
7802                 struct smb_Dir *dir_hnd = NULL;
7803                 const char *dname = NULL;
7804                 char *talloced = NULL;
7805                 long offset = 0;
7806
7807                 /*
7808                  * There is a wildcard that requires us to actually read the
7809                  * src dir and copy each file matching the mask to the dst.
7810                  * Right now streams won't be copied, but this could
7811                  * presumably be added with a nested loop for reach dir entry.
7812                  */
7813                 SMB_ASSERT(!smb_fname_src->stream_name);
7814                 SMB_ASSERT(!smb_fname_dst->stream_name);
7815
7816                 smb_fname_src->stream_name = NULL;
7817                 smb_fname_dst->stream_name = NULL;
7818
7819                 if (strequal(fname_src_mask,"????????.???")) {
7820                         TALLOC_FREE(fname_src_mask);
7821                         fname_src_mask = talloc_strdup(ctx, "*");
7822                         if (!fname_src_mask) {
7823                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7824                                 goto out;
7825                         }
7826                 }
7827
7828                 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7829                                         fname_src_dir,
7830                                         NULL,
7831                                         NULL,
7832                                         smb_fname_src->flags);
7833                 if (smb_fname_src_dir == NULL) {
7834                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7835                         goto out;
7836                 }
7837
7838                 status = check_name(conn, smb_fname_src_dir);
7839                 if (!NT_STATUS_IS_OK(status)) {
7840                         reply_nterror(req, status);
7841                         goto out;
7842                 }
7843
7844                 dir_hnd = OpenDir(ctx,
7845                                 conn,
7846                                 smb_fname_src_dir,
7847                                 fname_src_mask,
7848                                 0);
7849                 if (dir_hnd == NULL) {
7850                         status = map_nt_error_from_unix(errno);
7851                         reply_nterror(req, status);
7852                         goto out;
7853                 }
7854
7855                 error = ERRbadfile;
7856
7857                 /* Iterate over the src dir copying each entry to the dst. */
7858                 while ((dname = ReadDirName(dir_hnd, &offset,
7859                                             &smb_fname_src->st, &talloced))) {
7860                         char *destname = NULL;
7861
7862                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7863                                 TALLOC_FREE(talloced);
7864                                 continue;
7865                         }
7866
7867                         if (!is_visible_file(conn, fname_src_dir, dname,
7868                                              &smb_fname_src->st, false)) {
7869                                 TALLOC_FREE(talloced);
7870                                 continue;
7871                         }
7872
7873                         if(!mask_match(dname, fname_src_mask,
7874                                        conn->case_sensitive)) {
7875                                 TALLOC_FREE(talloced);
7876                                 continue;
7877                         }
7878
7879                         error = ERRnoaccess;
7880
7881                         /* Get the src smb_fname struct setup. */
7882                         TALLOC_FREE(smb_fname_src->base_name);
7883                         if (ISDOT(fname_src_dir)) {
7884                                 /* Ensure we use canonical names on open. */
7885                                 smb_fname_src->base_name =
7886                                         talloc_asprintf(smb_fname_src, "%s",
7887                                                 dname);
7888                         } else {
7889                                 smb_fname_src->base_name =
7890                                         talloc_asprintf(smb_fname_src, "%s/%s",
7891                                                 fname_src_dir, dname);
7892                         }
7893
7894                         if (!smb_fname_src->base_name) {
7895                                 TALLOC_FREE(dir_hnd);
7896                                 TALLOC_FREE(talloced);
7897                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7898                                 goto out;
7899                         }
7900
7901                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7902                                                smb_fname_dst->base_name,
7903                                                &destname)) {
7904                                 TALLOC_FREE(talloced);
7905                                 continue;
7906                         }
7907                         if (!destname) {
7908                                 TALLOC_FREE(dir_hnd);
7909                                 TALLOC_FREE(talloced);
7910                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7911                                 goto out;
7912                         }
7913
7914                         TALLOC_FREE(smb_fname_dst->base_name);
7915                         smb_fname_dst->base_name = destname;
7916
7917                         status = check_name(conn, smb_fname_src);
7918                         if (!NT_STATUS_IS_OK(status)) {
7919                                 TALLOC_FREE(dir_hnd);
7920                                 TALLOC_FREE(talloced);
7921                                 reply_nterror(req, status);
7922                                 goto out;
7923                         }
7924
7925                         status = check_name(conn, smb_fname_dst);
7926                         if (!NT_STATUS_IS_OK(status)) {
7927                                 TALLOC_FREE(dir_hnd);
7928                                 TALLOC_FREE(talloced);
7929                                 reply_nterror(req, status);
7930                                 goto out;
7931                         }
7932
7933                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7934                                 smb_fname_src->base_name,
7935                                 smb_fname_dst->base_name));
7936
7937                         status = copy_file(ctx, conn, smb_fname_src,
7938                                            smb_fname_dst, ofun, count,
7939                                            target_is_directory);
7940                         if (NT_STATUS_IS_OK(status)) {
7941                                 count++;
7942                         }
7943
7944                         TALLOC_FREE(talloced);
7945                 }
7946                 TALLOC_FREE(dir_hnd);
7947         }
7948
7949         if (count == 0) {
7950                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7951                 goto out;
7952         }
7953
7954         reply_outbuf(req, 1, 0);
7955         SSVAL(req->outbuf,smb_vwv0,count);
7956  out:
7957         TALLOC_FREE(smb_fname_src);
7958         TALLOC_FREE(smb_fname_src_dir);
7959         TALLOC_FREE(smb_fname_dst);
7960         TALLOC_FREE(fname_src);
7961         TALLOC_FREE(fname_dst);
7962         TALLOC_FREE(fname_src_mask);
7963         TALLOC_FREE(fname_src_dir);
7964
7965         END_PROFILE(SMBcopy);
7966         return;
7967 }
7968
7969 #undef DBGC_CLASS
7970 #define DBGC_CLASS DBGC_LOCKING
7971
7972 /****************************************************************************
7973  Get a lock pid, dealing with large count requests.
7974 ****************************************************************************/
7975
7976 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7977                     bool large_file_format)
7978 {
7979         if(!large_file_format)
7980                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7981         else
7982                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7983 }
7984
7985 /****************************************************************************
7986  Get a lock count, dealing with large count requests.
7987 ****************************************************************************/
7988
7989 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7990                         bool large_file_format)
7991 {
7992         uint64_t count = 0;
7993
7994         if(!large_file_format) {
7995                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7996         } else {
7997                 /*
7998                  * No BVAL, this is reversed!
7999                  */
8000                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8001                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8002         }
8003
8004         return count;
8005 }
8006
8007 /****************************************************************************
8008  Get a lock offset, dealing with large offset requests.
8009 ****************************************************************************/
8010
8011 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8012                          bool large_file_format)
8013 {
8014         uint64_t offset = 0;
8015
8016         if(!large_file_format) {
8017                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8018         } else {
8019                 /*
8020                  * No BVAL, this is reversed!
8021                  */
8022                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8023                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8024         }
8025
8026         return offset;
8027 }
8028
8029 NTSTATUS smbd_do_locking(struct smb_request *req,
8030                          files_struct *fsp,
8031                          uint8_t type,
8032                          int32_t timeout,
8033                          uint16_t num_locks,
8034                          struct smbd_lock_element *locks,
8035                          bool *async)
8036 {
8037         connection_struct *conn = req->conn;
8038         int i;
8039         NTSTATUS status = NT_STATUS_OK;
8040
8041         *async = false;
8042
8043         /* Setup the timeout in seconds. */
8044
8045         if (!lp_blocking_locks(SNUM(conn))) {
8046                 timeout = 0;
8047         }
8048
8049         for(i = 0; i < (int)num_locks; i++) {
8050                 struct smbd_lock_element *e = &locks[i];
8051
8052                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8053                           "%llu, file %s timeout = %d\n",
8054                           (double)e->offset,
8055                           (double)e->count,
8056                           (unsigned long long)e->smblctx,
8057                           fsp_str_dbg(fsp),
8058                           (int)timeout));
8059
8060                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8061                         struct blocking_lock_record *blr = NULL;
8062
8063                         if (num_locks > 1) {
8064                                 /*
8065                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8066                                  * if the lock vector contains one entry. When given multiple cancel
8067                                  * requests in a single PDU we expect the server to return an
8068                                  * error. Windows servers seem to accept the request but only
8069                                  * cancel the first lock.
8070                                  * JRA - Do what Windows does (tm) :-).
8071                                  */
8072
8073 #if 0
8074                                 /* MS-CIFS (2.2.4.32.1) behavior. */
8075                                 return NT_STATUS_DOS(ERRDOS,
8076                                                 ERRcancelviolation);
8077 #else
8078                                 /* Windows behavior. */
8079                                 if (i != 0) {
8080                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
8081                                                 "cancel request\n"));
8082                                         continue;
8083                                 }
8084 #endif
8085                         }
8086
8087                         if (lp_blocking_locks(SNUM(conn))) {
8088
8089                                 /* Schedule a message to ourselves to
8090                                    remove the blocking lock record and
8091                                    return the right error. */
8092
8093                                 blr = blocking_lock_cancel_smb1(fsp,
8094                                                 e->smblctx,
8095                                                 e->offset,
8096                                                 e->count,
8097                                                 WINDOWS_LOCK,
8098                                                 type,
8099                                                 NT_STATUS_FILE_LOCK_CONFLICT);
8100                                 if (blr == NULL) {
8101                                         return NT_STATUS_DOS(
8102                                                         ERRDOS,
8103                                                         ERRcancelviolation);
8104                                 }
8105                         }
8106                         /* Remove a matching pending lock. */
8107                         status = do_lock_cancel(fsp,
8108                                                 e->smblctx,
8109                                                 e->count,
8110                                                 e->offset,
8111                                                 WINDOWS_LOCK);
8112                 } else {
8113                         bool blocking_lock = timeout ? true : false;
8114                         bool defer_lock = false;
8115                         struct byte_range_lock *br_lck;
8116                         uint64_t block_smblctx;
8117
8118                         br_lck = do_lock(req->sconn->msg_ctx,
8119                                         fsp,
8120                                         e->smblctx,
8121                                         e->count,
8122                                         e->offset, 
8123                                         e->brltype,
8124                                         WINDOWS_LOCK,
8125                                         blocking_lock,
8126                                         &status,
8127                                         &block_smblctx);
8128
8129                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8130                                 /* Windows internal resolution for blocking locks seems
8131                                    to be about 200ms... Don't wait for less than that. JRA. */
8132                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8133                                         timeout = lp_lock_spin_time();
8134                                 }
8135                                 defer_lock = true;
8136                         }
8137
8138                         /* If a lock sent with timeout of zero would fail, and
8139                          * this lock has been requested multiple times,
8140                          * according to brl_lock_failed() we convert this
8141                          * request to a blocking lock with a timeout of between
8142                          * 150 - 300 milliseconds.
8143                          *
8144                          * If lp_lock_spin_time() has been set to 0, we skip
8145                          * this blocking retry and fail immediately.
8146                          *
8147                          * Replacement for do_lock_spin(). JRA. */
8148
8149                         if (!req->sconn->using_smb2 &&
8150                             br_lck && lp_blocking_locks(SNUM(conn)) &&
8151                             lp_lock_spin_time() && !blocking_lock &&
8152                             NT_STATUS_EQUAL((status),
8153                                 NT_STATUS_FILE_LOCK_CONFLICT))
8154                         {
8155                                 defer_lock = true;
8156                                 timeout = lp_lock_spin_time();
8157                         }
8158
8159                         if (br_lck && defer_lock) {
8160                                 /*
8161                                  * A blocking lock was requested. Package up
8162                                  * this smb into a queued request and push it
8163                                  * onto the blocking lock queue.
8164                                  */
8165                                 if(push_blocking_lock_request(br_lck,
8166                                                         req,
8167                                                         fsp,
8168                                                         timeout,
8169                                                         i,
8170                                                         e->smblctx,
8171                                                         e->brltype,
8172                                                         WINDOWS_LOCK,
8173                                                         e->offset,
8174                                                         e->count,
8175                                                         block_smblctx)) {
8176                                         TALLOC_FREE(br_lck);
8177                                         *async = true;
8178                                         return NT_STATUS_OK;
8179                                 }
8180                         }
8181
8182                         TALLOC_FREE(br_lck);
8183                 }
8184
8185                 if (!NT_STATUS_IS_OK(status)) {
8186                         break;
8187                 }
8188         }
8189
8190         /* If any of the above locks failed, then we must unlock
8191            all of the previous locks (X/Open spec). */
8192
8193         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8194
8195                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8196                         i = -1; /* we want to skip the for loop */
8197                 }
8198
8199                 /*
8200                  * Ensure we don't do a remove on the lock that just failed,
8201                  * as under POSIX rules, if we have a lock already there, we
8202                  * will delete it (and we shouldn't) .....
8203                  */
8204                 for(i--; i >= 0; i--) {
8205                         struct smbd_lock_element *e = &locks[i];
8206
8207                         do_unlock(req->sconn->msg_ctx,
8208                                 fsp,
8209                                 e->smblctx,
8210                                 e->count,
8211                                 e->offset,
8212                                 WINDOWS_LOCK);
8213                 }
8214                 return status;
8215         }
8216
8217         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8218                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8219
8220         return NT_STATUS_OK;
8221 }
8222
8223 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8224                            files_struct *fsp,
8225                            uint16_t num_ulocks,
8226                            struct smbd_lock_element *ulocks)
8227 {
8228         int i;
8229
8230         for(i = 0; i < (int)num_ulocks; i++) {
8231                 struct smbd_lock_element *e = &ulocks[i];
8232                 NTSTATUS status;
8233
8234                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8235                           "pid %u, file %s\n", __func__,
8236                           (double)e->offset,
8237                           (double)e->count,
8238                           (unsigned int)e->smblctx,
8239                           fsp_str_dbg(fsp)));
8240
8241                 if (e->brltype != UNLOCK_LOCK) {
8242                         /* this can only happen with SMB2 */
8243                         return NT_STATUS_INVALID_PARAMETER;
8244                 }
8245
8246                 status = do_unlock(req->sconn->msg_ctx,
8247                                 fsp,
8248                                 e->smblctx,
8249                                 e->count,
8250                                 e->offset,
8251                                 WINDOWS_LOCK);
8252
8253                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8254                            nt_errstr(status)));
8255
8256                 if (!NT_STATUS_IS_OK(status)) {
8257                         return status;
8258                 }
8259         }
8260
8261         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8262                   num_ulocks));
8263
8264         return NT_STATUS_OK;
8265 }
8266
8267 /****************************************************************************
8268  Reply to a lockingX request.
8269 ****************************************************************************/
8270
8271 void reply_lockingX(struct smb_request *req)
8272 {
8273         connection_struct *conn = req->conn;
8274         files_struct *fsp;
8275         unsigned char locktype;
8276         unsigned char oplocklevel;
8277         uint16_t num_ulocks;
8278         uint16_t num_locks;
8279         int32_t lock_timeout;
8280         int i;
8281         const uint8_t *data;
8282         bool large_file_format;
8283         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8284         struct smbd_lock_element *ulocks;
8285         struct smbd_lock_element *locks;
8286         bool async = false;
8287
8288         START_PROFILE(SMBlockingX);
8289
8290         if (req->wct < 8) {
8291                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8292                 END_PROFILE(SMBlockingX);
8293                 return;
8294         }
8295
8296         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8297         locktype = CVAL(req->vwv+3, 0);
8298         oplocklevel = CVAL(req->vwv+3, 1);
8299         num_ulocks = SVAL(req->vwv+6, 0);
8300         num_locks = SVAL(req->vwv+7, 0);
8301         lock_timeout = IVAL(req->vwv+4, 0);
8302         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8303
8304         if (!check_fsp(conn, req, fsp)) {
8305                 END_PROFILE(SMBlockingX);
8306                 return;
8307         }
8308
8309         data = req->buf;
8310
8311         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8312                 /* we don't support these - and CANCEL_LOCK makes w2k
8313                    and XP reboot so I don't really want to be
8314                    compatible! (tridge) */
8315                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8316                 END_PROFILE(SMBlockingX);
8317                 return;
8318         }
8319
8320         /* Check if this is an oplock break on a file
8321            we have granted an oplock on.
8322         */
8323         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8324                 /* Client can insist on breaking to none. */
8325                 bool break_to_none = (oplocklevel == 0);
8326                 bool result;
8327
8328                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8329                          "for %s\n", (unsigned int)oplocklevel,
8330                          fsp_fnum_dbg(fsp)));
8331
8332                 /*
8333                  * Make sure we have granted an exclusive or batch oplock on
8334                  * this file.
8335                  */
8336
8337                 if (fsp->oplock_type == 0) {
8338
8339                         /* The Samba4 nbench simulator doesn't understand
8340                            the difference between break to level2 and break
8341                            to none from level2 - it sends oplock break
8342                            replies in both cases. Don't keep logging an error
8343                            message here - just ignore it. JRA. */
8344
8345                         DEBUG(5,("reply_lockingX: Error : oplock break from "
8346                                  "client for %s (oplock=%d) and no "
8347                                  "oplock granted on this file (%s).\n",
8348                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
8349                                  fsp_str_dbg(fsp)));
8350
8351                         /* if this is a pure oplock break request then don't
8352                          * send a reply */
8353                         if (num_locks == 0 && num_ulocks == 0) {
8354                                 END_PROFILE(SMBlockingX);
8355                                 return;
8356                         } else {
8357                                 END_PROFILE(SMBlockingX);
8358                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8359                                 return;
8360                         }
8361                 }
8362
8363                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8364                     (break_to_none)) {
8365                         result = remove_oplock(fsp);
8366                 } else {
8367                         result = downgrade_oplock(fsp);
8368                 }
8369
8370                 if (!result) {
8371                         DEBUG(0, ("reply_lockingX: error in removing "
8372                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
8373                         /* Hmmm. Is this panic justified? */
8374                         smb_panic("internal tdb error");
8375                 }
8376
8377                 /* if this is a pure oplock break request then don't send a
8378                  * reply */
8379                 if (num_locks == 0 && num_ulocks == 0) {
8380                         /* Sanity check - ensure a pure oplock break is not a
8381                            chained request. */
8382                         if (CVAL(req->vwv+0, 0) != 0xff) {
8383                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8384                                          "break is a chained %d request !\n",
8385                                          (unsigned int)CVAL(req->vwv+0, 0)));
8386                         }
8387                         END_PROFILE(SMBlockingX);
8388                         return;
8389                 }
8390         }
8391
8392         if (req->buflen <
8393             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8394                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8395                 END_PROFILE(SMBlockingX);
8396                 return;
8397         }
8398
8399         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8400         if (ulocks == NULL) {
8401                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8402                 END_PROFILE(SMBlockingX);
8403                 return;
8404         }
8405
8406         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8407         if (locks == NULL) {
8408                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8409                 END_PROFILE(SMBlockingX);
8410                 return;
8411         }
8412
8413         /* Data now points at the beginning of the list
8414            of smb_unlkrng structs */
8415         for(i = 0; i < (int)num_ulocks; i++) {
8416                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8417                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8418                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8419                 ulocks[i].brltype = UNLOCK_LOCK;
8420         }
8421
8422         /* Now do any requested locks */
8423         data += ((large_file_format ? 20 : 10)*num_ulocks);
8424
8425         /* Data now points at the beginning of the list
8426            of smb_lkrng structs */
8427
8428         for(i = 0; i < (int)num_locks; i++) {
8429                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8430                 locks[i].count = get_lock_count(data, i, large_file_format);
8431                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8432
8433                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8434                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8435                                 locks[i].brltype = PENDING_READ_LOCK;
8436                         } else {
8437                                 locks[i].brltype = READ_LOCK;
8438                         }
8439                 } else {
8440                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8441                                 locks[i].brltype = PENDING_WRITE_LOCK;
8442                         } else {
8443                                 locks[i].brltype = WRITE_LOCK;
8444                         }
8445                 }
8446         }
8447
8448         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8449         if (!NT_STATUS_IS_OK(status)) {
8450                 END_PROFILE(SMBlockingX);
8451                 reply_nterror(req, status);
8452                 return;
8453         }
8454
8455         status = smbd_do_locking(req, fsp,
8456                                  locktype, lock_timeout,
8457                                  num_locks, locks,
8458                                  &async);
8459         if (!NT_STATUS_IS_OK(status)) {
8460                 END_PROFILE(SMBlockingX);
8461                 reply_nterror(req, status);
8462                 return;
8463         }
8464         if (async) {
8465                 END_PROFILE(SMBlockingX);
8466                 return;
8467         }
8468
8469         reply_outbuf(req, 2, 0);
8470         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8471         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8472
8473         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8474                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8475
8476         END_PROFILE(SMBlockingX);
8477 }
8478
8479 #undef DBGC_CLASS
8480 #define DBGC_CLASS DBGC_ALL
8481
8482 /****************************************************************************
8483  Reply to a SMBreadbmpx (read block multiplex) request.
8484  Always reply with an error, if someone has a platform really needs this,
8485  please contact vl@samba.org
8486 ****************************************************************************/
8487
8488 void reply_readbmpx(struct smb_request *req)
8489 {
8490         START_PROFILE(SMBreadBmpx);
8491         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8492         END_PROFILE(SMBreadBmpx);
8493         return;
8494 }
8495
8496 /****************************************************************************
8497  Reply to a SMBreadbs (read block multiplex secondary) request.
8498  Always reply with an error, if someone has a platform really needs this,
8499  please contact vl@samba.org
8500 ****************************************************************************/
8501
8502 void reply_readbs(struct smb_request *req)
8503 {
8504         START_PROFILE(SMBreadBs);
8505         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8506         END_PROFILE(SMBreadBs);
8507         return;
8508 }
8509
8510 /****************************************************************************
8511  Reply to a SMBsetattrE.
8512 ****************************************************************************/
8513
8514 void reply_setattrE(struct smb_request *req)
8515 {
8516         connection_struct *conn = req->conn;
8517         struct smb_file_time ft;
8518         files_struct *fsp;
8519         NTSTATUS status;
8520
8521         START_PROFILE(SMBsetattrE);
8522         ZERO_STRUCT(ft);
8523
8524         if (req->wct < 7) {
8525                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8526                 goto out;
8527         }
8528
8529         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8530
8531         if(!fsp || (fsp->conn != conn)) {
8532                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8533                 goto out;
8534         }
8535
8536         /*
8537          * Convert the DOS times into unix times.
8538          */
8539
8540         ft.atime = convert_time_t_to_timespec(
8541             srv_make_unix_date2(req->vwv+3));
8542         ft.mtime = convert_time_t_to_timespec(
8543             srv_make_unix_date2(req->vwv+5));
8544         ft.create_time = convert_time_t_to_timespec(
8545             srv_make_unix_date2(req->vwv+1));
8546
8547         reply_outbuf(req, 0, 0);
8548
8549         /* 
8550          * Patch from Ray Frush <frush@engr.colostate.edu>
8551          * Sometimes times are sent as zero - ignore them.
8552          */
8553
8554         /* Ensure we have a valid stat struct for the source. */
8555         status = vfs_stat_fsp(fsp);
8556         if (!NT_STATUS_IS_OK(status)) {
8557                 reply_nterror(req, status);
8558                 goto out;
8559         }
8560
8561         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8562                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8563                 goto out;
8564         }
8565
8566         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8567         if (!NT_STATUS_IS_OK(status)) {
8568                 reply_nterror(req, status);
8569                 goto out;
8570         }
8571
8572         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8573                " createtime=%u\n",
8574                 fsp_fnum_dbg(fsp),
8575                 (unsigned int)ft.atime.tv_sec,
8576                 (unsigned int)ft.mtime.tv_sec,
8577                 (unsigned int)ft.create_time.tv_sec
8578                 ));
8579  out:
8580         END_PROFILE(SMBsetattrE);
8581         return;
8582 }
8583
8584
8585 /* Back from the dead for OS/2..... JRA. */
8586
8587 /****************************************************************************
8588  Reply to a SMBwritebmpx (write block multiplex primary) request.
8589  Always reply with an error, if someone has a platform really needs this,
8590  please contact vl@samba.org
8591 ****************************************************************************/
8592
8593 void reply_writebmpx(struct smb_request *req)
8594 {
8595         START_PROFILE(SMBwriteBmpx);
8596         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8597         END_PROFILE(SMBwriteBmpx);
8598         return;
8599 }
8600
8601 /****************************************************************************
8602  Reply to a SMBwritebs (write block multiplex secondary) request.
8603  Always reply with an error, if someone has a platform really needs this,
8604  please contact vl@samba.org
8605 ****************************************************************************/
8606
8607 void reply_writebs(struct smb_request *req)
8608 {
8609         START_PROFILE(SMBwriteBs);
8610         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8611         END_PROFILE(SMBwriteBs);
8612         return;
8613 }
8614
8615 /****************************************************************************
8616  Reply to a SMBgetattrE.
8617 ****************************************************************************/
8618
8619 void reply_getattrE(struct smb_request *req)
8620 {
8621         connection_struct *conn = req->conn;
8622         int mode;
8623         files_struct *fsp;
8624         struct timespec create_ts;
8625
8626         START_PROFILE(SMBgetattrE);
8627
8628         if (req->wct < 1) {
8629                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8630                 END_PROFILE(SMBgetattrE);
8631                 return;
8632         }
8633
8634         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8635
8636         if(!fsp || (fsp->conn != conn)) {
8637                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8638                 END_PROFILE(SMBgetattrE);
8639                 return;
8640         }
8641
8642         /* Do an fstat on this file */
8643         if(fsp_stat(fsp)) {
8644                 reply_nterror(req, map_nt_error_from_unix(errno));
8645                 END_PROFILE(SMBgetattrE);
8646                 return;
8647         }
8648
8649         mode = dos_mode(conn, fsp->fsp_name);
8650
8651         /*
8652          * Convert the times into dos times. Set create
8653          * date to be last modify date as UNIX doesn't save
8654          * this.
8655          */
8656
8657         reply_outbuf(req, 11, 0);
8658
8659         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8660         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8661         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8662                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8663         /* Should we check pending modtime here ? JRA */
8664         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8665                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8666
8667         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8668                 SIVAL(req->outbuf, smb_vwv6, 0);
8669                 SIVAL(req->outbuf, smb_vwv8, 0);
8670         } else {
8671                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8672                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8673                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8674         }
8675         SSVAL(req->outbuf,smb_vwv10, mode);
8676
8677         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8678
8679         END_PROFILE(SMBgetattrE);
8680         return;
8681 }