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