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