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