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