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