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