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