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