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