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