s3:smbd: move sconn->smb1.echo_handler.* to xconn->smb1.echo_handler.*
[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 smbd_server_connection *sconn,
432                                      const char *name, int name_type)
433 {
434         struct smbXsrv_connection *xconn = sconn->conn;
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 smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
536 {
537         struct smbXsrv_connection *xconn = sconn->conn;
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(sconn, 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                         sconn->conn->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 smbd_server_connection *sconn = req->sconn;
697         struct smbXsrv_connection *xconn = sconn->conn;
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 smbd_server_connection *sconn = req->sconn;
775         struct smbXsrv_connection *xconn = sconn->conn;
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(req->sconn->conn,
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 smbd_server_connection *sconn = req->sconn;
1559         struct smbXsrv_connection *xconn = sconn->conn;
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(files_struct *fsp, off_t startpos, size_t nread)
3030 {
3031         struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
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 smbd_server_connection *sconn)
3166 {
3167         struct smbXsrv_connection *xconn = sconn->conn;
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 smbd_server_connection *sconn = req->sconn;
3202         struct smbXsrv_connection *xconn = sconn->conn;
3203         char *outbuf = NULL;
3204         ssize_t ret=0;
3205
3206         /*
3207          * We can only use sendfile on a non-chained packet 
3208          * but we can use on a non-oplocked file. tridge proved this
3209          * on a train in Germany :-). JRA.
3210          * reply_readbraw has already checked the length.
3211          */
3212
3213         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3214             (fsp->wcp == NULL) &&
3215             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3216                 ssize_t sendfile_read = -1;
3217                 char header[4];
3218                 DATA_BLOB header_blob;
3219
3220                 _smb_setlen(header,nread);
3221                 header_blob = data_blob_const(header, 4);
3222
3223                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3224                                                  &header_blob, startpos,
3225                                                  nread);
3226                 if (sendfile_read == -1) {
3227                         /* Returning ENOSYS means no data at all was sent.
3228                          * Do this as a normal read. */
3229                         if (errno == ENOSYS) {
3230                                 goto normal_readbraw;
3231                         }
3232
3233                         /*
3234                          * Special hack for broken Linux with no working sendfile. If we
3235                          * return EINTR we sent the header but not the rest of the data.
3236                          * Fake this up by doing read/write calls.
3237                          */
3238                         if (errno == EINTR) {
3239                                 /* Ensure we don't do this again. */
3240                                 set_use_sendfile(SNUM(conn), False);
3241                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242
3243                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
3244                                         DEBUG(0,("send_file_readbraw: "
3245                                                  "fake_sendfile failed for "
3246                                                  "file %s (%s).\n",
3247                                                  fsp_str_dbg(fsp),
3248                                                  strerror(errno)));
3249                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3250                                 }
3251                                 return;
3252                         }
3253
3254                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3255                                  "file %s (%s). Terminating\n",
3256                                  fsp_str_dbg(fsp), strerror(errno)));
3257                         exit_server_cleanly("send_file_readbraw sendfile failed");
3258                 } else if (sendfile_read == 0) {
3259                         /*
3260                          * Some sendfile implementations return 0 to indicate
3261                          * that there was a short read, but nothing was
3262                          * actually written to the socket.  In this case,
3263                          * fallback to the normal read path so the header gets
3264                          * the correct byte count.
3265                          */
3266                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3267                                   "bytes falling back to the normal read: "
3268                                   "%s\n", fsp_str_dbg(fsp)));
3269                         goto normal_readbraw;
3270                 }
3271
3272                 /* Deal with possible short send. */
3273                 if (sendfile_read != 4+nread) {
3274                         sendfile_short_send(fsp, sendfile_read, 4, nread);
3275                 }
3276                 return;
3277         }
3278
3279 normal_readbraw:
3280
3281         outbuf = talloc_array(NULL, char, nread+4);
3282         if (!outbuf) {
3283                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3284                         (unsigned)(nread+4)));
3285                 reply_readbraw_error(sconn);
3286                 return;
3287         }
3288
3289         if (nread > 0) {
3290                 ret = read_file(fsp,outbuf+4,startpos,nread);
3291 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3292                 if (ret < mincount)
3293                         ret = 0;
3294 #else
3295                 if (ret < nread)
3296                         ret = 0;
3297 #endif
3298         }
3299
3300         _smb_setlen(outbuf,ret);
3301         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3302                 int saved_errno = errno;
3303                 /*
3304                  * Try and give an error message saying what
3305                  * client failed.
3306                  */
3307                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3308                           smbXsrv_connection_dbg(xconn),
3309                           strerror(saved_errno)));
3310                 errno = saved_errno;
3311
3312                 fail_readraw();
3313         }
3314
3315         TALLOC_FREE(outbuf);
3316 }
3317
3318 /****************************************************************************
3319  Reply to a readbraw (core+ protocol).
3320 ****************************************************************************/
3321
3322 void reply_readbraw(struct smb_request *req)
3323 {
3324         connection_struct *conn = req->conn;
3325         struct smbd_server_connection *sconn = req->sconn;
3326         struct smbXsrv_connection *xconn = sconn->conn;
3327         ssize_t maxcount,mincount;
3328         size_t nread = 0;
3329         off_t startpos;
3330         files_struct *fsp;
3331         struct lock_struct lock;
3332         off_t size = 0;
3333
3334         START_PROFILE(SMBreadbraw);
3335
3336         if (srv_is_signing_active(xconn) || req->encrypted) {
3337                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3338                         "raw reads/writes are disallowed.");
3339         }
3340
3341         if (req->wct < 8) {
3342                 reply_readbraw_error(sconn);
3343                 END_PROFILE(SMBreadbraw);
3344                 return;
3345         }
3346
3347         if (xconn->smb1.echo_handler.trusted_fde) {
3348                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3349                          "'async smb echo handler = yes'\n"));
3350                 reply_readbraw_error(sconn);
3351                 END_PROFILE(SMBreadbraw);
3352                 return;
3353         }
3354
3355         /*
3356          * Special check if an oplock break has been issued
3357          * and the readraw request croses on the wire, we must
3358          * return a zero length response here.
3359          */
3360
3361         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3362
3363         /*
3364          * We have to do a check_fsp by hand here, as
3365          * we must always return 4 zero bytes on error,
3366          * not a NTSTATUS.
3367          */
3368
3369         if (!fsp || !conn || conn != fsp->conn ||
3370                         req->vuid != fsp->vuid ||
3371                         fsp->is_directory || fsp->fh->fd == -1) {
3372                 /*
3373                  * fsp could be NULL here so use the value from the packet. JRA.
3374                  */
3375                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3376                         "- cache prime?\n",
3377                         (int)SVAL(req->vwv+0, 0)));
3378                 reply_readbraw_error(sconn);
3379                 END_PROFILE(SMBreadbraw);
3380                 return;
3381         }
3382
3383         /* Do a "by hand" version of CHECK_READ. */
3384         if (!(fsp->can_read ||
3385                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3386                                 (fsp->access_mask & FILE_EXECUTE)))) {
3387                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3388                                 (int)SVAL(req->vwv+0, 0)));
3389                 reply_readbraw_error(sconn);
3390                 END_PROFILE(SMBreadbraw);
3391                 return;
3392         }
3393
3394         flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3395
3396         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3397         if(req->wct == 10) {
3398                 /*
3399                  * This is a large offset (64 bit) read.
3400                  */
3401
3402                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3403
3404                 if(startpos < 0) {
3405                         DEBUG(0,("reply_readbraw: negative 64 bit "
3406                                 "readraw offset (%.0f) !\n",
3407                                 (double)startpos ));
3408                         reply_readbraw_error(sconn);
3409                         END_PROFILE(SMBreadbraw);
3410                         return;
3411                 }
3412         }
3413
3414         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3415         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3416
3417         /* ensure we don't overrun the packet size */
3418         maxcount = MIN(65535,maxcount);
3419
3420         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3421             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3422             &lock);
3423
3424         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3425                 reply_readbraw_error(sconn);
3426                 END_PROFILE(SMBreadbraw);
3427                 return;
3428         }
3429
3430         if (fsp_stat(fsp) == 0) {
3431                 size = fsp->fsp_name->st.st_ex_size;
3432         }
3433
3434         if (startpos >= size) {
3435                 nread = 0;
3436         } else {
3437                 nread = MIN(maxcount,(size - startpos));
3438         }
3439
3440 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3441         if (nread < mincount)
3442                 nread = 0;
3443 #endif
3444
3445         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3446                 "min=%lu nread=%lu\n",
3447                 fsp_fnum_dbg(fsp), (double)startpos,
3448                 (unsigned long)maxcount,
3449                 (unsigned long)mincount,
3450                 (unsigned long)nread ) );
3451
3452         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3453
3454         DEBUG(5,("reply_readbraw finished\n"));
3455
3456         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3457
3458         END_PROFILE(SMBreadbraw);
3459         return;
3460 }
3461
3462 #undef DBGC_CLASS
3463 #define DBGC_CLASS DBGC_LOCKING
3464
3465 /****************************************************************************
3466  Reply to a lockread (core+ protocol).
3467 ****************************************************************************/
3468
3469 void reply_lockread(struct smb_request *req)
3470 {
3471         connection_struct *conn = req->conn;
3472         ssize_t nread = -1;
3473         char *data;
3474         off_t startpos;
3475         size_t numtoread;
3476         size_t maxtoread;
3477         NTSTATUS status;
3478         files_struct *fsp;
3479         struct byte_range_lock *br_lck = NULL;
3480         char *p = NULL;
3481         struct smbd_server_connection *sconn = req->sconn;
3482         struct smbXsrv_connection *xconn = sconn->conn;
3483
3484         START_PROFILE(SMBlockread);
3485
3486         if (req->wct < 5) {
3487                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3488                 END_PROFILE(SMBlockread);
3489                 return;
3490         }
3491
3492         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3493
3494         if (!check_fsp(conn, req, fsp)) {
3495                 END_PROFILE(SMBlockread);
3496                 return;
3497         }
3498
3499         if (!CHECK_READ(fsp,req)) {
3500                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3501                 END_PROFILE(SMBlockread);
3502                 return;
3503         }
3504
3505         numtoread = SVAL(req->vwv+1, 0);
3506         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3507
3508         /*
3509          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3510          * protocol request that predates the read/write lock concept. 
3511          * Thus instead of asking for a read lock here we need to ask
3512          * for a write lock. JRA.
3513          * Note that the requested lock size is unaffected by max_send.
3514          */
3515
3516         br_lck = do_lock(req->sconn->msg_ctx,
3517                         fsp,
3518                         (uint64_t)req->smbpid,
3519                         (uint64_t)numtoread,
3520                         (uint64_t)startpos,
3521                         WRITE_LOCK,
3522                         WINDOWS_LOCK,
3523                         False, /* Non-blocking lock. */
3524                         &status,
3525                         NULL);
3526         TALLOC_FREE(br_lck);
3527
3528         if (NT_STATUS_V(status)) {
3529                 reply_nterror(req, status);
3530                 END_PROFILE(SMBlockread);
3531                 return;
3532         }
3533
3534         /*
3535          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3536          */
3537         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3538
3539         if (numtoread > maxtoread) {
3540                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3541 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3542                         (unsigned int)numtoread, (unsigned int)maxtoread,
3543                         (unsigned int)xconn->smb1.sessions.max_send));
3544                 numtoread = maxtoread;
3545         }
3546
3547         reply_outbuf(req, 5, numtoread + 3);
3548
3549         data = smb_buf(req->outbuf) + 3;
3550
3551         nread = read_file(fsp,data,startpos,numtoread);
3552
3553         if (nread < 0) {
3554                 reply_nterror(req, map_nt_error_from_unix(errno));
3555                 END_PROFILE(SMBlockread);
3556                 return;
3557         }
3558
3559         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3560
3561         SSVAL(req->outbuf,smb_vwv0,nread);
3562         SSVAL(req->outbuf,smb_vwv5,nread+3);
3563         p = smb_buf(req->outbuf);
3564         SCVAL(p,0,0); /* pad byte. */
3565         SSVAL(p,1,nread);
3566
3567         DEBUG(3,("lockread %s num=%d nread=%d\n",
3568                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3569
3570         END_PROFILE(SMBlockread);
3571         return;
3572 }
3573
3574 #undef DBGC_CLASS
3575 #define DBGC_CLASS DBGC_ALL
3576
3577 /****************************************************************************
3578  Reply to a read.
3579 ****************************************************************************/
3580
3581 void reply_read(struct smb_request *req)
3582 {
3583         connection_struct *conn = req->conn;
3584         size_t numtoread;
3585         size_t maxtoread;
3586         ssize_t nread = 0;
3587         char *data;
3588         off_t startpos;
3589         files_struct *fsp;
3590         struct lock_struct lock;
3591         struct smbd_server_connection *sconn = req->sconn;
3592         struct smbXsrv_connection *xconn = sconn->conn;
3593
3594         START_PROFILE(SMBread);
3595
3596         if (req->wct < 3) {
3597                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3598                 END_PROFILE(SMBread);
3599                 return;
3600         }
3601
3602         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3603
3604         if (!check_fsp(conn, req, fsp)) {
3605                 END_PROFILE(SMBread);
3606                 return;
3607         }
3608
3609         if (!CHECK_READ(fsp,req)) {
3610                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3611                 END_PROFILE(SMBread);
3612                 return;
3613         }
3614
3615         numtoread = SVAL(req->vwv+1, 0);
3616         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3617
3618         /*
3619          * The requested read size cannot be greater than max_send. JRA.
3620          */
3621         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3622
3623         if (numtoread > maxtoread) {
3624                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3625 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3626                         (unsigned int)numtoread, (unsigned int)maxtoread,
3627                         (unsigned int)xconn->smb1.sessions.max_send));
3628                 numtoread = maxtoread;
3629         }
3630
3631         reply_outbuf(req, 5, numtoread+3);
3632
3633         data = smb_buf(req->outbuf) + 3;
3634
3635         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3636             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3637             &lock);
3638
3639         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3640                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3641                 END_PROFILE(SMBread);
3642                 return;
3643         }
3644
3645         if (numtoread > 0)
3646                 nread = read_file(fsp,data,startpos,numtoread);
3647
3648         if (nread < 0) {
3649                 reply_nterror(req, map_nt_error_from_unix(errno));
3650                 goto strict_unlock;
3651         }
3652
3653         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3654
3655         SSVAL(req->outbuf,smb_vwv0,nread);
3656         SSVAL(req->outbuf,smb_vwv5,nread+3);
3657         SCVAL(smb_buf(req->outbuf),0,1);
3658         SSVAL(smb_buf(req->outbuf),1,nread);
3659
3660         DEBUG(3, ("read %s num=%d nread=%d\n",
3661                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3662
3663 strict_unlock:
3664         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3665
3666         END_PROFILE(SMBread);
3667         return;
3668 }
3669
3670 /****************************************************************************
3671  Setup readX header.
3672 ****************************************************************************/
3673
3674 static int setup_readX_header(struct smb_request *req, char *outbuf,
3675                               size_t smb_maxcnt)
3676 {
3677         int outsize;
3678
3679         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3680
3681         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3682
3683         SCVAL(outbuf,smb_vwv0,0xFF);
3684         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3685         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3686         SSVAL(outbuf,smb_vwv6,
3687               (smb_wct - 4)     /* offset from smb header to wct */
3688               + 1               /* the wct field */
3689               + 12 * sizeof(uint16_t) /* vwv */
3690               + 2);             /* the buflen field */
3691         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3692         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3693         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3694         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3695         return outsize;
3696 }
3697
3698 /****************************************************************************
3699  Reply to a read and X - possibly using sendfile.
3700 ****************************************************************************/
3701
3702 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3703                             files_struct *fsp, off_t startpos,
3704                             size_t smb_maxcnt)
3705 {
3706         struct smbXsrv_connection *xconn = req->sconn->conn;
3707         ssize_t nread = -1;
3708         struct lock_struct lock;
3709         int saved_errno = 0;
3710
3711         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3712             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3713             &lock);
3714
3715         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3716                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3717                 return;
3718         }
3719
3720         /*
3721          * We can only use sendfile on a non-chained packet
3722          * but we can use on a non-oplocked file. tridge proved this
3723          * on a train in Germany :-). JRA.
3724          */
3725
3726         if (!req_is_in_chain(req) &&
3727             !req->encrypted &&
3728             (fsp->base_fsp == NULL) &&
3729             (fsp->wcp == NULL) &&
3730             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3731                 uint8 headerbuf[smb_size + 12 * 2];
3732                 DATA_BLOB header;
3733
3734                 if(fsp_stat(fsp) == -1) {
3735                         reply_nterror(req, map_nt_error_from_unix(errno));
3736                         goto strict_unlock;
3737                 }
3738
3739                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3740                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3741                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3742                         /*
3743                          * We already know that we would do a short read, so don't
3744                          * try the sendfile() path.
3745                          */
3746                         goto nosendfile_read;
3747                 }
3748
3749                 /*
3750                  * Set up the packet header before send. We
3751                  * assume here the sendfile will work (get the
3752                  * correct amount of data).
3753                  */
3754
3755                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3756
3757                 construct_reply_common_req(req, (char *)headerbuf);
3758                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3759
3760                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3761                                          startpos, smb_maxcnt);
3762                 if (nread == -1) {
3763                         saved_errno = errno;
3764
3765                         /* Returning ENOSYS means no data at all was sent.
3766                            Do this as a normal read. */
3767                         if (errno == ENOSYS) {
3768                                 goto normal_read;
3769                         }
3770
3771                         /*
3772                          * Special hack for broken Linux with no working sendfile. If we
3773                          * return EINTR we sent the header but not the rest of the data.
3774                          * Fake this up by doing read/write calls.
3775                          */
3776
3777                         if (errno == EINTR) {
3778                                 /* Ensure we don't do this again. */
3779                                 set_use_sendfile(SNUM(conn), False);
3780                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3781                                 nread = fake_sendfile(fsp, startpos,
3782                                                       smb_maxcnt);
3783                                 if (nread == -1) {
3784                                         saved_errno = errno;
3785                                         DEBUG(0,("send_file_readX: "
3786                                                  "fake_sendfile failed for "
3787                                                  "file %s (%s) for client %s. "
3788                                                  "Terminating\n",
3789                                                  fsp_str_dbg(fsp),
3790                                                  smbXsrv_connection_dbg(xconn),
3791                                                  strerror(saved_errno)));
3792                                         errno = saved_errno;
3793                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3794                                 }
3795                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3796                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3797                                 /* No outbuf here means successful sendfile. */
3798                                 goto strict_unlock;
3799                         }
3800
3801                         DEBUG(0,("send_file_readX: sendfile failed for file "
3802                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3803                                  strerror(errno)));
3804                         exit_server_cleanly("send_file_readX sendfile failed");
3805                 } else if (nread == 0) {
3806                         /*
3807                          * Some sendfile implementations return 0 to indicate
3808                          * that there was a short read, but nothing was
3809                          * actually written to the socket.  In this case,
3810                          * fallback to the normal read path so the header gets
3811                          * the correct byte count.
3812                          */
3813                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3814                                   "falling back to the normal read: %s\n",
3815                                   fsp_str_dbg(fsp)));
3816                         goto normal_read;
3817                 }
3818
3819                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3820                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3821
3822                 /* Deal with possible short send. */
3823                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3824                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3825                 }
3826                 /* No outbuf here means successful sendfile. */
3827                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3828                 SMB_PERFCOUNT_END(&req->pcd);
3829                 goto strict_unlock;
3830         }
3831
3832 normal_read:
3833
3834         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3835                 uint8 headerbuf[smb_size + 2*12];
3836                 ssize_t ret;
3837
3838                 construct_reply_common_req(req, (char *)headerbuf);
3839                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3840
3841                 /* Send out the header. */
3842                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3843                                  sizeof(headerbuf));
3844                 if (ret != sizeof(headerbuf)) {
3845                         saved_errno = errno;
3846                         /*
3847                          * Try and give an error message saying what
3848                          * client failed.
3849                          */
3850                         DEBUG(0,("send_file_readX: write_data failed for file "
3851                                  "%s (%s) for client %s. Terminating\n",
3852                                  fsp_str_dbg(fsp),
3853                                  smbXsrv_connection_dbg(xconn),
3854                                  strerror(saved_errno)));
3855                         errno = saved_errno;
3856                         exit_server_cleanly("send_file_readX sendfile failed");
3857                 }
3858                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3859                 if (nread == -1) {
3860                         saved_errno = errno;
3861                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3862                                  "%s (%s) for client %s. Terminating\n",
3863                                  fsp_str_dbg(fsp),
3864                                  smbXsrv_connection_dbg(xconn),
3865                                  strerror(saved_errno)));
3866                         errno = saved_errno;
3867                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3868                 }
3869                 goto strict_unlock;
3870         }
3871
3872 nosendfile_read:
3873
3874         reply_outbuf(req, 12, smb_maxcnt);
3875         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3876         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3877
3878         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3879         saved_errno = errno;
3880
3881         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3882
3883         if (nread < 0) {
3884                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3885                 return;
3886         }
3887
3888         setup_readX_header(req, (char *)req->outbuf, nread);
3889
3890         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3891                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3892         return;
3893
3894  strict_unlock:
3895         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3896         TALLOC_FREE(req->outbuf);
3897         return;
3898 }
3899
3900 /****************************************************************************
3901  Work out how much space we have for a read return.
3902 ****************************************************************************/
3903
3904 static size_t calc_max_read_pdu(const struct smb_request *req)
3905 {
3906         struct smbXsrv_connection *xconn = req->sconn->conn;
3907
3908         if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3909                 return xconn->smb1.sessions.max_send;
3910         }
3911
3912         if (!lp_large_readwrite()) {
3913                 return xconn->smb1.sessions.max_send;
3914         }
3915
3916         if (req_is_in_chain(req)) {
3917                 return xconn->smb1.sessions.max_send;
3918         }
3919
3920         if (req->encrypted) {
3921                 /*
3922                  * Don't take encrypted traffic up to the
3923                  * limit. There are padding considerations
3924                  * that make that tricky.
3925                  */
3926                 return xconn->smb1.sessions.max_send;
3927         }
3928
3929         if (srv_is_signing_active(xconn)) {
3930                 return 0x1FFFF;
3931         }
3932
3933         if (!lp_unix_extensions()) {
3934                 return 0x1FFFF;
3935         }
3936
3937         /*
3938          * We can do ultra-large POSIX reads.
3939          */
3940         return 0xFFFFFF;
3941 }
3942
3943 /****************************************************************************
3944  Calculate how big a read can be. Copes with all clients. It's always
3945  safe to return a short read - Windows does this.
3946 ****************************************************************************/
3947
3948 static size_t calc_read_size(const struct smb_request *req,
3949                              size_t upper_size,
3950                              size_t lower_size)
3951 {
3952         size_t max_pdu = calc_max_read_pdu(req);
3953         size_t total_size = 0;
3954         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3955         size_t max_len = max_pdu - hdr_len;
3956
3957         /*
3958          * Windows explicitly ignores upper size of 0xFFFF.
3959          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3960          * We must do the same as these will never fit even in
3961          * an extended size NetBIOS packet.
3962          */
3963         if (upper_size == 0xFFFF) {
3964                 upper_size = 0;
3965         }
3966
3967         if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3968                 upper_size = 0;
3969         }
3970
3971         total_size = ((upper_size<<16) | lower_size);
3972
3973         /*
3974          * LARGE_READX test shows it's always safe to return
3975          * a short read. Windows does so.
3976          */
3977         return MIN(total_size, max_len);
3978 }
3979
3980 /****************************************************************************
3981  Reply to a read and X.
3982 ****************************************************************************/
3983
3984 void reply_read_and_X(struct smb_request *req)
3985 {
3986         connection_struct *conn = req->conn;
3987         files_struct *fsp;
3988         off_t startpos;
3989         size_t smb_maxcnt;
3990         size_t upper_size;
3991         bool big_readX = False;
3992 #if 0
3993         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3994 #endif
3995
3996         START_PROFILE(SMBreadX);
3997
3998         if ((req->wct != 10) && (req->wct != 12)) {
3999                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4000                 return;
4001         }
4002
4003         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4004         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4005         smb_maxcnt = SVAL(req->vwv+5, 0);
4006
4007         /* If it's an IPC, pass off the pipe handler. */
4008         if (IS_IPC(conn)) {
4009                 reply_pipe_read_and_X(req);
4010                 END_PROFILE(SMBreadX);
4011                 return;
4012         }
4013
4014         if (!check_fsp(conn, req, fsp)) {
4015                 END_PROFILE(SMBreadX);
4016                 return;
4017         }
4018
4019         if (!CHECK_READ(fsp,req)) {
4020                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4021                 END_PROFILE(SMBreadX);
4022                 return;
4023         }
4024
4025         upper_size = SVAL(req->vwv+7, 0);
4026         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4027         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4028                 /*
4029                  * This is a heuristic to avoid keeping large
4030                  * outgoing buffers around over long-lived aio
4031                  * requests.
4032                  */
4033                 big_readX = True;
4034         }
4035
4036         if (req->wct == 12) {
4037                 /*
4038                  * This is a large offset (64 bit) read.
4039                  */
4040                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4041
4042         }
4043
4044         if (!big_readX) {
4045                 NTSTATUS status = schedule_aio_read_and_X(conn,
4046                                         req,
4047                                         fsp,
4048                                         startpos,
4049                                         smb_maxcnt);
4050                 if (NT_STATUS_IS_OK(status)) {
4051                         /* Read scheduled - we're done. */
4052                         goto out;
4053                 }
4054                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4055                         /* Real error - report to client. */
4056                         END_PROFILE(SMBreadX);
4057                         reply_nterror(req, status);
4058                         return;
4059                 }
4060                 /* NT_STATUS_RETRY - fall back to sync read. */
4061         }
4062
4063         smbd_lock_socket(req->sconn);
4064         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4065         smbd_unlock_socket(req->sconn);
4066
4067  out:
4068         END_PROFILE(SMBreadX);
4069         return;
4070 }
4071
4072 /****************************************************************************
4073  Error replies to writebraw must have smb_wct == 1. Fix this up.
4074 ****************************************************************************/
4075
4076 void error_to_writebrawerr(struct smb_request *req)
4077 {
4078         uint8 *old_outbuf = req->outbuf;
4079
4080         reply_outbuf(req, 1, 0);
4081
4082         memcpy(req->outbuf, old_outbuf, smb_size);
4083         TALLOC_FREE(old_outbuf);
4084 }
4085
4086 /****************************************************************************
4087  Read 4 bytes of a smb packet and return the smb length of the packet.
4088  Store the result in the buffer. This version of the function will
4089  never return a session keepalive (length of zero).
4090  Timeout is in milliseconds.
4091 ****************************************************************************/
4092
4093 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4094                                 size_t *len)
4095 {
4096         uint8_t msgtype = NBSSkeepalive;
4097
4098         while (msgtype == NBSSkeepalive) {
4099                 NTSTATUS status;
4100
4101                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4102                                                           len);
4103                 if (!NT_STATUS_IS_OK(status)) {
4104                         char addr[INET6_ADDRSTRLEN];
4105                         /* Try and give an error message
4106                          * saying what client failed. */
4107                         DEBUG(0, ("read_fd_with_timeout failed for "
4108                                   "client %s read error = %s.\n",
4109                                   get_peer_addr(fd,addr,sizeof(addr)),
4110                                   nt_errstr(status)));
4111                         return status;
4112                 }
4113
4114                 msgtype = CVAL(inbuf, 0);
4115         }
4116
4117         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4118                   (unsigned long)len));
4119
4120         return NT_STATUS_OK;
4121 }
4122
4123 /****************************************************************************
4124  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4125 ****************************************************************************/
4126
4127 void reply_writebraw(struct smb_request *req)
4128 {
4129         connection_struct *conn = req->conn;
4130         struct smbXsrv_connection *xconn = req->sconn->conn;
4131         char *buf = NULL;
4132         ssize_t nwritten=0;
4133         ssize_t total_written=0;
4134         size_t numtowrite=0;
4135         size_t tcount;
4136         off_t startpos;
4137         const char *data=NULL;
4138         bool write_through;
4139         files_struct *fsp;
4140         struct lock_struct lock;
4141         NTSTATUS status;
4142
4143         START_PROFILE(SMBwritebraw);
4144
4145         /*
4146          * If we ever reply with an error, it must have the SMB command
4147          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4148          * we're finished.
4149          */
4150         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4151
4152         if (srv_is_signing_active(xconn)) {
4153                 END_PROFILE(SMBwritebraw);
4154                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4155                                 "raw reads/writes are disallowed.");
4156         }
4157
4158         if (req->wct < 12) {
4159                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4160                 error_to_writebrawerr(req);
4161                 END_PROFILE(SMBwritebraw);
4162                 return;
4163         }
4164
4165         if (xconn->smb1.echo_handler.trusted_fde) {
4166                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4167                          "'async smb echo handler = yes'\n"));
4168                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4169                 error_to_writebrawerr(req);
4170                 END_PROFILE(SMBwritebraw);
4171                 return;
4172         }
4173
4174         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4175         if (!check_fsp(conn, req, fsp)) {
4176                 error_to_writebrawerr(req);
4177                 END_PROFILE(SMBwritebraw);
4178                 return;
4179         }
4180
4181         if (!CHECK_WRITE(fsp)) {
4182                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4183                 error_to_writebrawerr(req);
4184                 END_PROFILE(SMBwritebraw);
4185                 return;
4186         }
4187
4188         tcount = IVAL(req->vwv+1, 0);
4189         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4190         write_through = BITSETW(req->vwv+7,0);
4191
4192         /* We have to deal with slightly different formats depending
4193                 on whether we are using the core+ or lanman1.0 protocol */
4194
4195         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4196                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4197                 data = smb_buf_const(req->inbuf);
4198         } else {
4199                 numtowrite = SVAL(req->vwv+10, 0);
4200                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4201         }
4202
4203         /* Ensure we don't write bytes past the end of this packet. */
4204         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4205                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4206                 error_to_writebrawerr(req);
4207                 END_PROFILE(SMBwritebraw);
4208                 return;
4209         }
4210
4211         if (!fsp->print_file) {
4212                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4213                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4214                     &lock);
4215
4216                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4217                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4218                         error_to_writebrawerr(req);
4219                         END_PROFILE(SMBwritebraw);
4220                         return;
4221                 }
4222         }
4223
4224         if (numtowrite>0) {
4225                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4226         }
4227
4228         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4229                         "wrote=%d sync=%d\n",
4230                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4231                 (int)nwritten, (int)write_through));
4232
4233         if (nwritten < (ssize_t)numtowrite)  {
4234                 reply_nterror(req, NT_STATUS_DISK_FULL);
4235                 error_to_writebrawerr(req);
4236                 goto strict_unlock;
4237         }
4238
4239         total_written = nwritten;
4240
4241         /* Allocate a buffer of 64k + length. */
4242         buf = talloc_array(NULL, char, 65540);
4243         if (!buf) {
4244                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4245                 error_to_writebrawerr(req);
4246                 goto strict_unlock;
4247         }
4248
4249         /* Return a SMBwritebraw message to the redirector to tell
4250          * it to send more bytes */
4251
4252         memcpy(buf, req->inbuf, smb_size);
4253         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4254         SCVAL(buf,smb_com,SMBwritebraw);
4255         SSVALS(buf,smb_vwv0,0xFFFF);
4256         show_msg(buf);
4257         if (!srv_send_smb(req->sconn,
4258                           buf,
4259                           false, 0, /* no signing */
4260                           IS_CONN_ENCRYPTED(conn),
4261                           &req->pcd)) {
4262                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4263                         "failed.");
4264         }
4265
4266         /* Now read the raw data into the buffer and write it */
4267         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4268                                  &numtowrite);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 exit_server_cleanly("secondary writebraw failed");
4271         }
4272
4273         /* Set up outbuf to return the correct size */
4274         reply_outbuf(req, 1, 0);
4275
4276         if (numtowrite != 0) {
4277
4278                 if (numtowrite > 0xFFFF) {
4279                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4280                                 "raw requested (%u). Terminating\n",
4281                                 (unsigned int)numtowrite ));
4282                         exit_server_cleanly("secondary writebraw failed");
4283                 }
4284
4285                 if (tcount > nwritten+numtowrite) {
4286                         DEBUG(3,("reply_writebraw: Client overestimated the "
4287                                 "write %d %d %d\n",
4288                                 (int)tcount,(int)nwritten,(int)numtowrite));
4289                 }
4290
4291                 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4292
4293                 if (!NT_STATUS_IS_OK(status)) {
4294                         /* Try and give an error message
4295                          * saying what client failed. */
4296                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4297                                   "raw read failed (%s) for client %s. "
4298                                   "Terminating\n", nt_errstr(status),
4299                                   smbXsrv_connection_dbg(xconn)));
4300                         exit_server_cleanly("secondary writebraw failed");
4301                 }
4302
4303                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4304                 if (nwritten == -1) {
4305                         TALLOC_FREE(buf);
4306                         reply_nterror(req, map_nt_error_from_unix(errno));
4307                         error_to_writebrawerr(req);
4308                         goto strict_unlock;
4309                 }
4310
4311                 if (nwritten < (ssize_t)numtowrite) {
4312                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4313                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4314                 }
4315
4316                 if (nwritten > 0) {
4317                         total_written += nwritten;
4318                 }
4319         }
4320
4321         TALLOC_FREE(buf);
4322         SSVAL(req->outbuf,smb_vwv0,total_written);
4323
4324         status = sync_file(conn, fsp, write_through);
4325         if (!NT_STATUS_IS_OK(status)) {
4326                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4327                          fsp_str_dbg(fsp), nt_errstr(status)));
4328                 reply_nterror(req, status);
4329                 error_to_writebrawerr(req);
4330                 goto strict_unlock;
4331         }
4332
4333         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4334                 "wrote=%d\n",
4335                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4336                 (int)total_written));
4337
4338         if (!fsp->print_file) {
4339                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4340         }
4341
4342         /* We won't return a status if write through is not selected - this
4343          * follows what WfWg does */
4344         END_PROFILE(SMBwritebraw);
4345
4346         if (!write_through && total_written==tcount) {
4347
4348 #if RABBIT_PELLET_FIX
4349                 /*
4350                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4351                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4352                  * JRA.
4353                  */
4354                 if (!send_keepalive(xconn->transport.sock)) {
4355                         exit_server_cleanly("reply_writebraw: send of "
4356                                 "keepalive failed");
4357                 }
4358 #endif
4359                 TALLOC_FREE(req->outbuf);
4360         }
4361         return;
4362
4363 strict_unlock:
4364         if (!fsp->print_file) {
4365                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4366         }
4367
4368         END_PROFILE(SMBwritebraw);
4369         return;
4370 }
4371
4372 #undef DBGC_CLASS
4373 #define DBGC_CLASS DBGC_LOCKING
4374
4375 /****************************************************************************
4376  Reply to a writeunlock (core+).
4377 ****************************************************************************/
4378
4379 void reply_writeunlock(struct smb_request *req)
4380 {
4381         connection_struct *conn = req->conn;
4382         ssize_t nwritten = -1;
4383         size_t numtowrite;
4384         off_t startpos;
4385         const char *data;
4386         NTSTATUS status = NT_STATUS_OK;
4387         files_struct *fsp;
4388         struct lock_struct lock;
4389         int saved_errno = 0;
4390
4391         START_PROFILE(SMBwriteunlock);
4392
4393         if (req->wct < 5) {
4394                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4395                 END_PROFILE(SMBwriteunlock);
4396                 return;
4397         }
4398
4399         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4400
4401         if (!check_fsp(conn, req, fsp)) {
4402                 END_PROFILE(SMBwriteunlock);
4403                 return;
4404         }
4405
4406         if (!CHECK_WRITE(fsp)) {
4407                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4408                 END_PROFILE(SMBwriteunlock);
4409                 return;
4410         }
4411
4412         numtowrite = SVAL(req->vwv+1, 0);
4413         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4414         data = (const char *)req->buf + 3;
4415
4416         if (!fsp->print_file && numtowrite > 0) {
4417                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4418                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4419                     &lock);
4420
4421                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4422                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4423                         END_PROFILE(SMBwriteunlock);
4424                         return;
4425                 }
4426         }
4427
4428         /* The special X/Open SMB protocol handling of
4429            zero length writes is *NOT* done for
4430            this call */
4431         if(numtowrite == 0) {
4432                 nwritten = 0;
4433         } else {
4434                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4435                 saved_errno = errno;
4436         }
4437
4438         status = sync_file(conn, fsp, False /* write through */);
4439         if (!NT_STATUS_IS_OK(status)) {
4440                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4441                          fsp_str_dbg(fsp), nt_errstr(status)));
4442                 reply_nterror(req, status);
4443                 goto strict_unlock;
4444         }
4445
4446         if(nwritten < 0) {
4447                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4448                 goto strict_unlock;
4449         }
4450
4451         if((nwritten < numtowrite) && (numtowrite != 0)) {
4452                 reply_nterror(req, NT_STATUS_DISK_FULL);
4453                 goto strict_unlock;
4454         }
4455
4456         if (numtowrite && !fsp->print_file) {
4457                 status = do_unlock(req->sconn->msg_ctx,
4458                                 fsp,
4459                                 (uint64_t)req->smbpid,
4460                                 (uint64_t)numtowrite, 
4461                                 (uint64_t)startpos,
4462                                 WINDOWS_LOCK);
4463
4464                 if (NT_STATUS_V(status)) {
4465                         reply_nterror(req, status);
4466                         goto strict_unlock;
4467                 }
4468         }
4469
4470         reply_outbuf(req, 1, 0);
4471
4472         SSVAL(req->outbuf,smb_vwv0,nwritten);
4473
4474         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4475                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4476
4477 strict_unlock:
4478         if (numtowrite && !fsp->print_file) {
4479                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4480         }
4481
4482         END_PROFILE(SMBwriteunlock);
4483         return;
4484 }
4485
4486 #undef DBGC_CLASS
4487 #define DBGC_CLASS DBGC_ALL
4488
4489 /****************************************************************************
4490  Reply to a write.
4491 ****************************************************************************/
4492
4493 void reply_write(struct smb_request *req)
4494 {
4495         connection_struct *conn = req->conn;
4496         size_t numtowrite;
4497         ssize_t nwritten = -1;
4498         off_t startpos;
4499         const char *data;
4500         files_struct *fsp;
4501         struct lock_struct lock;
4502         NTSTATUS status;
4503         int saved_errno = 0;
4504
4505         START_PROFILE(SMBwrite);
4506
4507         if (req->wct < 5) {
4508                 END_PROFILE(SMBwrite);
4509                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4510                 return;
4511         }
4512
4513         /* If it's an IPC, pass off the pipe handler. */
4514         if (IS_IPC(conn)) {
4515                 reply_pipe_write(req);
4516                 END_PROFILE(SMBwrite);
4517                 return;
4518         }
4519
4520         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4521
4522         if (!check_fsp(conn, req, fsp)) {
4523                 END_PROFILE(SMBwrite);
4524                 return;
4525         }
4526
4527         if (!CHECK_WRITE(fsp)) {
4528                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4529                 END_PROFILE(SMBwrite);
4530                 return;
4531         }
4532
4533         numtowrite = SVAL(req->vwv+1, 0);
4534         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4535         data = (const char *)req->buf + 3;
4536
4537         if (!fsp->print_file) {
4538                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4539                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4540                         &lock);
4541
4542                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4543                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4544                         END_PROFILE(SMBwrite);
4545                         return;
4546                 }
4547         }
4548
4549         /*
4550          * X/Open SMB protocol says that if smb_vwv1 is
4551          * zero then the file size should be extended or
4552          * truncated to the size given in smb_vwv[2-3].
4553          */
4554
4555         if(numtowrite == 0) {
4556                 /*
4557                  * This is actually an allocate call, and set EOF. JRA.
4558                  */
4559                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4560                 if (nwritten < 0) {
4561                         reply_nterror(req, NT_STATUS_DISK_FULL);
4562                         goto strict_unlock;
4563                 }
4564                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4565                 if (nwritten < 0) {
4566                         reply_nterror(req, NT_STATUS_DISK_FULL);
4567                         goto strict_unlock;
4568                 }
4569                 trigger_write_time_update_immediate(fsp);
4570         } else {
4571                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4572         }
4573
4574         status = sync_file(conn, fsp, False);
4575         if (!NT_STATUS_IS_OK(status)) {
4576                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4577                          fsp_str_dbg(fsp), nt_errstr(status)));
4578                 reply_nterror(req, status);
4579                 goto strict_unlock;
4580         }
4581
4582         if(nwritten < 0) {
4583                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4584                 goto strict_unlock;
4585         }
4586
4587         if((nwritten == 0) && (numtowrite != 0)) {
4588                 reply_nterror(req, NT_STATUS_DISK_FULL);
4589                 goto strict_unlock;
4590         }
4591
4592         reply_outbuf(req, 1, 0);
4593
4594         SSVAL(req->outbuf,smb_vwv0,nwritten);
4595
4596         if (nwritten < (ssize_t)numtowrite) {
4597                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4598                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4599         }
4600
4601         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4602
4603 strict_unlock:
4604         if (!fsp->print_file) {
4605                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4606         }
4607
4608         END_PROFILE(SMBwrite);
4609         return;
4610 }
4611
4612 /****************************************************************************
4613  Ensure a buffer is a valid writeX for recvfile purposes.
4614 ****************************************************************************/
4615
4616 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4617                                                 (2*14) + /* word count (including bcc) */ \
4618                                                 1 /* pad byte */)
4619
4620 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4621                             const uint8_t *inbuf)
4622 {
4623         size_t numtowrite;
4624         unsigned int doff = 0;
4625         size_t len = smb_len_large(inbuf);
4626         uint16_t fnum;
4627         struct smbXsrv_open *op = NULL;
4628         struct files_struct *fsp = NULL;
4629         NTSTATUS status;
4630
4631         if (is_encrypted_packet(sconn, inbuf)) {
4632                 /* Can't do this on encrypted
4633                  * connections. */
4634                 return false;
4635         }
4636
4637         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4638                 return false;
4639         }
4640
4641         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4642                         CVAL(inbuf,smb_wct) != 14) {
4643                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4644                         "invalid word length.\n"));
4645                 return false;
4646         }
4647
4648         fnum = SVAL(inbuf, smb_vwv2);
4649         status = smb1srv_open_lookup(sconn->conn,
4650                                      fnum,
4651                                      0, /* now */
4652                                      &op);
4653         if (!NT_STATUS_IS_OK(status)) {
4654                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4655                 return false;
4656         }
4657         fsp = op->compat;
4658         if (fsp == NULL) {
4659                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4660                 return false;
4661         }
4662         if (fsp->conn == NULL) {
4663                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4664                 return false;
4665         }
4666
4667         if (IS_IPC(fsp->conn)) {
4668                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4669                 return false;
4670         }
4671         if (IS_PRINT(fsp->conn)) {
4672                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4673                 return false;
4674         }
4675         doff = SVAL(inbuf,smb_vwv11);
4676
4677         numtowrite = SVAL(inbuf,smb_vwv10);
4678
4679         if (len > doff && len - doff > 0xFFFF) {
4680                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4681         }
4682
4683         if (numtowrite == 0) {
4684                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4685                 return false;
4686         }
4687
4688         /* Ensure the sizes match up. */
4689         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4690                 /* no pad byte...old smbclient :-( */
4691                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4692                         (unsigned int)doff,
4693                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4694                 return false;
4695         }
4696
4697         if (len - doff != numtowrite) {
4698                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4699                         "len = %u, doff = %u, numtowrite = %u\n",
4700                         (unsigned int)len,
4701                         (unsigned int)doff,
4702                         (unsigned int)numtowrite ));
4703                 return false;
4704         }
4705
4706         DEBUG(10,("is_valid_writeX_buffer: true "
4707                 "len = %u, doff = %u, numtowrite = %u\n",
4708                 (unsigned int)len,
4709                 (unsigned int)doff,
4710                 (unsigned int)numtowrite ));
4711
4712         return true;
4713 }
4714
4715 /****************************************************************************
4716  Reply to a write and X.
4717 ****************************************************************************/
4718
4719 void reply_write_and_X(struct smb_request *req)
4720 {
4721         connection_struct *conn = req->conn;
4722         struct smbXsrv_connection *xconn = req->sconn->conn;
4723         files_struct *fsp;
4724         struct lock_struct lock;
4725         off_t startpos;
4726         size_t numtowrite;
4727         bool write_through;
4728         ssize_t nwritten;
4729         unsigned int smb_doff;
4730         unsigned int smblen;
4731         const char *data;
4732         NTSTATUS status;
4733         int saved_errno = 0;
4734
4735         START_PROFILE(SMBwriteX);
4736
4737         if ((req->wct != 12) && (req->wct != 14)) {
4738                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4739                 goto out;
4740         }
4741
4742         numtowrite = SVAL(req->vwv+10, 0);
4743         smb_doff = SVAL(req->vwv+11, 0);
4744         smblen = smb_len(req->inbuf);
4745
4746         if (req->unread_bytes > 0xFFFF ||
4747                         (smblen > smb_doff &&
4748                                 smblen - smb_doff > 0xFFFF)) {
4749                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4750         }
4751
4752         if (req->unread_bytes) {
4753                 /* Can't do a recvfile write on IPC$ */
4754                 if (IS_IPC(conn)) {
4755                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4756                         goto out;
4757                 }
4758                 if (numtowrite != req->unread_bytes) {
4759                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760                         goto out;
4761                 }
4762         } else {
4763                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4764                                 smb_doff + numtowrite > smblen) {
4765                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4766                         goto out;
4767                 }
4768         }
4769
4770         /* If it's an IPC, pass off the pipe handler. */
4771         if (IS_IPC(conn)) {
4772                 if (req->unread_bytes) {
4773                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774                         goto out;
4775                 }
4776                 reply_pipe_write_and_X(req);
4777                 goto out;
4778         }
4779
4780         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4781         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4782         write_through = BITSETW(req->vwv+7,0);
4783
4784         if (!check_fsp(conn, req, fsp)) {
4785                 goto out;
4786         }
4787
4788         if (!CHECK_WRITE(fsp)) {
4789                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4790                 goto out;
4791         }
4792
4793         data = smb_base(req->inbuf) + smb_doff;
4794
4795         if(req->wct == 14) {
4796                 /*
4797                  * This is a large offset (64 bit) write.
4798                  */
4799                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4800
4801         }
4802
4803         /* X/Open SMB protocol says that, unlike SMBwrite
4804         if the length is zero then NO truncation is
4805         done, just a write of zero. To truncate a file,
4806         use SMBwrite. */
4807
4808         if(numtowrite == 0) {
4809                 nwritten = 0;
4810         } else {
4811                 if (req->unread_bytes == 0) {
4812                         status = schedule_aio_write_and_X(conn,
4813                                                 req,
4814                                                 fsp,
4815                                                 data,
4816                                                 startpos,
4817                                                 numtowrite);
4818
4819                         if (NT_STATUS_IS_OK(status)) {
4820                                 /* write scheduled - we're done. */
4821                                 goto out;
4822                         }
4823                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4824                                 /* Real error - report to client. */
4825                                 reply_nterror(req, status);
4826                                 goto out;
4827                         }
4828                         /* NT_STATUS_RETRY - fall through to sync write. */
4829                 }
4830
4831                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4832                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4833                     &lock);
4834
4835                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4836                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4837                         goto out;
4838                 }
4839
4840                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4841                 saved_errno = errno;
4842
4843                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4844         }
4845
4846         if(nwritten < 0) {
4847                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4848                 goto out;
4849         }
4850
4851         if((nwritten == 0) && (numtowrite != 0)) {
4852                 reply_nterror(req, NT_STATUS_DISK_FULL);
4853                 goto out;
4854         }
4855
4856         reply_outbuf(req, 6, 0);
4857         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4858         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4859         SSVAL(req->outbuf,smb_vwv2,nwritten);
4860         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4861
4862         DEBUG(3,("writeX %s num=%d wrote=%d\n",
4863                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4864
4865         status = sync_file(conn, fsp, write_through);
4866         if (!NT_STATUS_IS_OK(status)) {
4867                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4868                          fsp_str_dbg(fsp), nt_errstr(status)));
4869                 reply_nterror(req, status);
4870                 goto out;
4871         }
4872
4873         END_PROFILE(SMBwriteX);
4874         return;
4875
4876 out:
4877         if (req->unread_bytes) {
4878                 /* writeX failed. drain socket. */
4879                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4880                                 req->unread_bytes) {
4881                         smb_panic("failed to drain pending bytes");
4882                 }
4883                 req->unread_bytes = 0;
4884         }
4885
4886         END_PROFILE(SMBwriteX);
4887         return;
4888 }
4889
4890 /****************************************************************************
4891  Reply to a lseek.
4892 ****************************************************************************/
4893
4894 void reply_lseek(struct smb_request *req)
4895 {
4896         connection_struct *conn = req->conn;
4897         off_t startpos;
4898         off_t res= -1;
4899         int mode,umode;
4900         files_struct *fsp;
4901
4902         START_PROFILE(SMBlseek);
4903
4904         if (req->wct < 4) {
4905                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4906                 END_PROFILE(SMBlseek);
4907                 return;
4908         }
4909
4910         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4911
4912         if (!check_fsp(conn, req, fsp)) {
4913                 return;
4914         }
4915
4916         flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4917
4918         mode = SVAL(req->vwv+1, 0) & 3;
4919         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4920         startpos = (off_t)IVALS(req->vwv+2, 0);
4921
4922         switch (mode) {
4923                 case 0:
4924                         umode = SEEK_SET;
4925                         res = startpos;
4926                         break;
4927                 case 1:
4928                         umode = SEEK_CUR;
4929                         res = fsp->fh->pos + startpos;
4930                         break;
4931                 case 2:
4932                         umode = SEEK_END;
4933                         break;
4934                 default:
4935                         umode = SEEK_SET;
4936                         res = startpos;
4937                         break;
4938         }
4939
4940         if (umode == SEEK_END) {
4941                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4942                         if(errno == EINVAL) {
4943                                 off_t current_pos = startpos;
4944
4945                                 if(fsp_stat(fsp) == -1) {
4946                                         reply_nterror(req,
4947                                                 map_nt_error_from_unix(errno));
4948                                         END_PROFILE(SMBlseek);
4949                                         return;
4950                                 }
4951
4952                                 current_pos += fsp->fsp_name->st.st_ex_size;
4953                                 if(current_pos < 0)
4954                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4955                         }
4956                 }
4957
4958                 if(res == -1) {
4959                         reply_nterror(req, map_nt_error_from_unix(errno));
4960                         END_PROFILE(SMBlseek);
4961                         return;
4962                 }
4963         }
4964
4965         fsp->fh->pos = res;
4966
4967         reply_outbuf(req, 2, 0);
4968         SIVAL(req->outbuf,smb_vwv0,res);
4969
4970         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4971                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4972
4973         END_PROFILE(SMBlseek);
4974         return;
4975 }
4976
4977 /****************************************************************************
4978  Reply to a flush.
4979 ****************************************************************************/
4980
4981 void reply_flush(struct smb_request *req)
4982 {
4983         connection_struct *conn = req->conn;
4984         uint16 fnum;
4985         files_struct *fsp;
4986
4987         START_PROFILE(SMBflush);
4988
4989         if (req->wct < 1) {
4990                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4991                 return;
4992         }
4993
4994         fnum = SVAL(req->vwv+0, 0);
4995         fsp = file_fsp(req, fnum);
4996
4997         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4998                 return;
4999         }
5000
5001         if (!fsp) {
5002                 file_sync_all(conn);
5003         } else {
5004                 NTSTATUS status = sync_file(conn, fsp, True);
5005                 if (!NT_STATUS_IS_OK(status)) {
5006                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5007                                 fsp_str_dbg(fsp), nt_errstr(status)));
5008                         reply_nterror(req, status);
5009                         END_PROFILE(SMBflush);
5010                         return;
5011                 }
5012         }
5013
5014         reply_outbuf(req, 0, 0);
5015
5016         DEBUG(3,("flush\n"));
5017         END_PROFILE(SMBflush);
5018         return;
5019 }
5020
5021 /****************************************************************************
5022  Reply to a exit.
5023  conn POINTER CAN BE NULL HERE !
5024 ****************************************************************************/
5025
5026 void reply_exit(struct smb_request *req)
5027 {
5028         START_PROFILE(SMBexit);
5029
5030         file_close_pid(req->sconn, req->smbpid, req->vuid);
5031
5032         reply_outbuf(req, 0, 0);
5033
5034         DEBUG(3,("exit\n"));
5035
5036         END_PROFILE(SMBexit);
5037         return;
5038 }
5039
5040 struct reply_close_state {
5041         files_struct *fsp;
5042         struct smb_request *smbreq;
5043 };
5044
5045 static void do_smb1_close(struct tevent_req *req);
5046
5047 void reply_close(struct smb_request *req)
5048 {
5049         connection_struct *conn = req->conn;
5050         NTSTATUS status = NT_STATUS_OK;
5051         files_struct *fsp = NULL;
5052         START_PROFILE(SMBclose);
5053
5054         if (req->wct < 3) {
5055                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5056                 END_PROFILE(SMBclose);
5057                 return;
5058         }
5059
5060         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5061
5062         /*
5063          * We can only use check_fsp if we know it's not a directory.
5064          */
5065
5066         if (!check_fsp_open(conn, req, fsp)) {
5067                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5068                 END_PROFILE(SMBclose);
5069                 return;
5070         }
5071
5072         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5073                   fsp->is_directory ? "directory" : "file",
5074                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5075                   conn->num_files_open));
5076
5077         if (!fsp->is_directory) {
5078                 time_t t;
5079
5080                 /*
5081                  * Take care of any time sent in the close.
5082                  */
5083
5084                 t = srv_make_unix_date3(req->vwv+1);
5085                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5086         }
5087
5088         if (fsp->num_aio_requests != 0) {
5089
5090                 struct reply_close_state *state;
5091
5092                 DEBUG(10, ("closing with aio %u requests pending\n",
5093                            fsp->num_aio_requests));
5094
5095                 /*
5096                  * We depend on the aio_extra destructor to take care of this
5097                  * close request once fsp->num_aio_request drops to 0.
5098                  */
5099
5100                 fsp->deferred_close = tevent_wait_send(
5101                         fsp, fsp->conn->sconn->ev_ctx);
5102                 if (fsp->deferred_close == NULL) {
5103                         status = NT_STATUS_NO_MEMORY;
5104                         goto done;
5105                 }
5106
5107                 state = talloc(fsp, struct reply_close_state);
5108                 if (state == NULL) {
5109                         TALLOC_FREE(fsp->deferred_close);
5110                         status = NT_STATUS_NO_MEMORY;
5111                         goto done;
5112                 }
5113                 state->fsp = fsp;
5114                 state->smbreq = talloc_move(fsp, &req);
5115                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5116                                         state);
5117                 END_PROFILE(SMBclose);
5118                 return;
5119         }
5120
5121         /*
5122          * close_file() returns the unix errno if an error was detected on
5123          * close - normally this is due to a disk full error. If not then it
5124          * was probably an I/O error.
5125          */
5126
5127         status = close_file(req, fsp, NORMAL_CLOSE);
5128 done:
5129         if (!NT_STATUS_IS_OK(status)) {
5130                 reply_nterror(req, status);
5131                 END_PROFILE(SMBclose);
5132                 return;
5133         }
5134
5135         reply_outbuf(req, 0, 0);
5136         END_PROFILE(SMBclose);
5137         return;
5138 }
5139
5140 static void do_smb1_close(struct tevent_req *req)
5141 {
5142         struct reply_close_state *state = tevent_req_callback_data(
5143                 req, struct reply_close_state);
5144         struct smb_request *smbreq;
5145         NTSTATUS status;
5146         int ret;
5147
5148         ret = tevent_wait_recv(req);
5149         TALLOC_FREE(req);
5150         if (ret != 0) {
5151                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5152                            strerror(ret)));
5153                 /*
5154                  * Continue anyway, this should never happen
5155                  */
5156         }
5157
5158         /*
5159          * fsp->smb2_close_request right now is a talloc grandchild of
5160          * fsp. When we close_file(fsp), it would go with it. No chance to
5161          * reply...
5162          */
5163         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5164
5165         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5166         if (NT_STATUS_IS_OK(status)) {
5167                 reply_outbuf(smbreq, 0, 0);
5168         } else {
5169                 reply_nterror(smbreq, status);
5170         }
5171         if (!srv_send_smb(smbreq->sconn,
5172                         (char *)smbreq->outbuf,
5173                         true,
5174                         smbreq->seqnum+1,
5175                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5176                         NULL)) {
5177                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5178                                     "failed.");
5179         }
5180         TALLOC_FREE(smbreq);
5181 }
5182
5183 /****************************************************************************
5184  Reply to a writeclose (Core+ protocol).
5185 ****************************************************************************/
5186
5187 void reply_writeclose(struct smb_request *req)
5188 {
5189         connection_struct *conn = req->conn;
5190         size_t numtowrite;
5191         ssize_t nwritten = -1;
5192         NTSTATUS close_status = NT_STATUS_OK;
5193         off_t startpos;
5194         const char *data;
5195         struct timespec mtime;
5196         files_struct *fsp;
5197         struct lock_struct lock;
5198
5199         START_PROFILE(SMBwriteclose);
5200
5201         if (req->wct < 6) {
5202                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5203                 END_PROFILE(SMBwriteclose);
5204                 return;
5205         }
5206
5207         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5208
5209         if (!check_fsp(conn, req, fsp)) {
5210                 END_PROFILE(SMBwriteclose);
5211                 return;
5212         }
5213         if (!CHECK_WRITE(fsp)) {
5214                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5215                 END_PROFILE(SMBwriteclose);
5216                 return;
5217         }
5218
5219         numtowrite = SVAL(req->vwv+1, 0);
5220         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5221         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5222         data = (const char *)req->buf + 1;
5223
5224         if (fsp->print_file == NULL) {
5225                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5226                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5227                     &lock);
5228
5229                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5230                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5231                         END_PROFILE(SMBwriteclose);
5232                         return;
5233                 }
5234         }
5235
5236         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5237
5238         if (fsp->print_file == NULL) {
5239                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5240         }
5241
5242         set_close_write_time(fsp, mtime);
5243
5244         /*
5245          * More insanity. W2K only closes the file if writelen > 0.
5246          * JRA.
5247          */
5248
5249         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5250                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5251                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5252
5253         if (numtowrite) {
5254                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5255                          "file %s\n", fsp_str_dbg(fsp)));
5256                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5257                 fsp = NULL;
5258         }
5259
5260         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5261                 reply_nterror(req, NT_STATUS_DISK_FULL);
5262                 goto out;
5263         }
5264
5265         if(!NT_STATUS_IS_OK(close_status)) {
5266                 reply_nterror(req, close_status);
5267                 goto out;
5268         }
5269
5270         reply_outbuf(req, 1, 0);
5271
5272         SSVAL(req->outbuf,smb_vwv0,nwritten);
5273
5274 out:
5275
5276         END_PROFILE(SMBwriteclose);
5277         return;
5278 }
5279
5280 #undef DBGC_CLASS
5281 #define DBGC_CLASS DBGC_LOCKING
5282
5283 /****************************************************************************
5284  Reply to a lock.
5285 ****************************************************************************/
5286
5287 void reply_lock(struct smb_request *req)
5288 {
5289         connection_struct *conn = req->conn;
5290         uint64_t count,offset;
5291         NTSTATUS status;
5292         files_struct *fsp;
5293         struct byte_range_lock *br_lck = NULL;
5294
5295         START_PROFILE(SMBlock);
5296
5297         if (req->wct < 5) {
5298                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5299                 END_PROFILE(SMBlock);
5300                 return;
5301         }
5302
5303         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5304
5305         if (!check_fsp(conn, req, fsp)) {
5306                 END_PROFILE(SMBlock);
5307                 return;
5308         }
5309
5310         count = (uint64_t)IVAL(req->vwv+1, 0);
5311         offset = (uint64_t)IVAL(req->vwv+3, 0);
5312
5313         DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5314                  fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5315
5316         br_lck = do_lock(req->sconn->msg_ctx,
5317                         fsp,
5318                         (uint64_t)req->smbpid,
5319                         count,
5320                         offset,
5321                         WRITE_LOCK,
5322                         WINDOWS_LOCK,
5323                         False, /* Non-blocking lock. */
5324                         &status,
5325                         NULL);
5326
5327         TALLOC_FREE(br_lck);
5328
5329         if (NT_STATUS_V(status)) {
5330                 reply_nterror(req, status);
5331                 END_PROFILE(SMBlock);
5332                 return;
5333         }
5334
5335         reply_outbuf(req, 0, 0);
5336
5337         END_PROFILE(SMBlock);
5338         return;
5339 }
5340
5341 /****************************************************************************
5342  Reply to a unlock.
5343 ****************************************************************************/
5344
5345 void reply_unlock(struct smb_request *req)
5346 {
5347         connection_struct *conn = req->conn;
5348         uint64_t count,offset;
5349         NTSTATUS status;
5350         files_struct *fsp;
5351
5352         START_PROFILE(SMBunlock);
5353
5354         if (req->wct < 5) {
5355                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5356                 END_PROFILE(SMBunlock);
5357                 return;
5358         }
5359
5360         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5361
5362         if (!check_fsp(conn, req, fsp)) {
5363                 END_PROFILE(SMBunlock);
5364                 return;
5365         }
5366
5367         count = (uint64_t)IVAL(req->vwv+1, 0);
5368         offset = (uint64_t)IVAL(req->vwv+3, 0);
5369
5370         status = do_unlock(req->sconn->msg_ctx,
5371                         fsp,
5372                         (uint64_t)req->smbpid,
5373                         count,
5374                         offset,
5375                         WINDOWS_LOCK);
5376
5377         if (NT_STATUS_V(status)) {
5378                 reply_nterror(req, status);
5379                 END_PROFILE(SMBunlock);
5380                 return;
5381         }
5382
5383         DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5384                     fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5385
5386         reply_outbuf(req, 0, 0);
5387
5388         END_PROFILE(SMBunlock);
5389         return;
5390 }
5391
5392 #undef DBGC_CLASS
5393 #define DBGC_CLASS DBGC_ALL
5394
5395 /****************************************************************************
5396  Reply to a tdis.
5397  conn POINTER CAN BE NULL HERE !
5398 ****************************************************************************/
5399
5400 void reply_tdis(struct smb_request *req)
5401 {
5402         NTSTATUS status;
5403         connection_struct *conn = req->conn;
5404         struct smbXsrv_tcon *tcon;
5405
5406         START_PROFILE(SMBtdis);
5407
5408         if (!conn) {
5409                 DEBUG(4,("Invalid connection in tdis\n"));
5410                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5411                 END_PROFILE(SMBtdis);
5412                 return;
5413         }
5414
5415         tcon = conn->tcon;
5416         req->conn = NULL;
5417
5418         /*
5419          * TODO: cancel all outstanding requests on the tcon
5420          */
5421         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5422         if (!NT_STATUS_IS_OK(status)) {
5423                 DEBUG(0, ("reply_tdis: "
5424                           "smbXsrv_tcon_disconnect() failed: %s\n",
5425                           nt_errstr(status)));
5426                 /*
5427                  * If we hit this case, there is something completely
5428                  * wrong, so we better disconnect the transport connection.
5429                  */
5430                 END_PROFILE(SMBtdis);
5431                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5432                 return;
5433         }
5434
5435         TALLOC_FREE(tcon);
5436
5437         reply_outbuf(req, 0, 0);
5438         END_PROFILE(SMBtdis);
5439         return;
5440 }
5441
5442 /****************************************************************************
5443  Reply to a echo.
5444  conn POINTER CAN BE NULL HERE !
5445 ****************************************************************************/
5446
5447 void reply_echo(struct smb_request *req)
5448 {
5449         connection_struct *conn = req->conn;
5450         struct smb_perfcount_data local_pcd;
5451         struct smb_perfcount_data *cur_pcd;
5452         int smb_reverb;
5453         int seq_num;
5454
5455         START_PROFILE(SMBecho);
5456
5457         smb_init_perfcount_data(&local_pcd);
5458
5459         if (req->wct < 1) {
5460                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5461                 END_PROFILE(SMBecho);
5462                 return;
5463         }
5464
5465         smb_reverb = SVAL(req->vwv+0, 0);
5466
5467         reply_outbuf(req, 1, req->buflen);
5468
5469         /* copy any incoming data back out */
5470         if (req->buflen > 0) {
5471                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5472         }
5473
5474         if (smb_reverb > 100) {
5475                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5476                 smb_reverb = 100;
5477         }
5478
5479         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5480
5481                 /* this makes sure we catch the request pcd */
5482                 if (seq_num == smb_reverb) {
5483                         cur_pcd = &req->pcd;
5484                 } else {
5485                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5486                         cur_pcd = &local_pcd;
5487                 }
5488
5489                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5490
5491                 show_msg((char *)req->outbuf);
5492                 if (!srv_send_smb(req->sconn,
5493                                 (char *)req->outbuf,
5494                                 true, req->seqnum+1,
5495                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5496                                 cur_pcd))
5497                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5498         }
5499
5500         DEBUG(3,("echo %d times\n", smb_reverb));
5501
5502         TALLOC_FREE(req->outbuf);
5503
5504         END_PROFILE(SMBecho);
5505         return;
5506 }
5507
5508 /****************************************************************************
5509  Reply to a printopen.
5510 ****************************************************************************/
5511
5512 void reply_printopen(struct smb_request *req)
5513 {
5514         connection_struct *conn = req->conn;
5515         files_struct *fsp;
5516         NTSTATUS status;
5517
5518         START_PROFILE(SMBsplopen);
5519
5520         if (req->wct < 2) {
5521                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5522                 END_PROFILE(SMBsplopen);
5523                 return;
5524         }
5525
5526         if (!CAN_PRINT(conn)) {
5527                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5528                 END_PROFILE(SMBsplopen);
5529                 return;
5530         }
5531
5532         status = file_new(req, conn, &fsp);
5533         if(!NT_STATUS_IS_OK(status)) {
5534                 reply_nterror(req, status);
5535                 END_PROFILE(SMBsplopen);
5536                 return;
5537         }
5538
5539         /* Open for exclusive use, write only. */
5540         status = print_spool_open(fsp, NULL, req->vuid);
5541
5542         if (!NT_STATUS_IS_OK(status)) {
5543                 file_free(req, fsp);
5544                 reply_nterror(req, status);
5545                 END_PROFILE(SMBsplopen);
5546                 return;
5547         }
5548
5549         reply_outbuf(req, 1, 0);
5550         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5551
5552         DEBUG(3,("openprint fd=%d %s\n",
5553                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5554
5555         END_PROFILE(SMBsplopen);
5556         return;
5557 }
5558
5559 /****************************************************************************
5560  Reply to a printclose.
5561 ****************************************************************************/
5562
5563 void reply_printclose(struct smb_request *req)
5564 {
5565         connection_struct *conn = req->conn;
5566         files_struct *fsp;
5567         NTSTATUS status;
5568
5569         START_PROFILE(SMBsplclose);
5570
5571         if (req->wct < 1) {
5572                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5573                 END_PROFILE(SMBsplclose);
5574                 return;
5575         }
5576
5577         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5578
5579         if (!check_fsp(conn, req, fsp)) {
5580                 END_PROFILE(SMBsplclose);
5581                 return;
5582         }
5583
5584         if (!CAN_PRINT(conn)) {
5585                 reply_force_doserror(req, ERRSRV, ERRerror);
5586                 END_PROFILE(SMBsplclose);
5587                 return;
5588         }
5589
5590         DEBUG(3,("printclose fd=%d %s\n",
5591                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5592
5593         status = close_file(req, fsp, NORMAL_CLOSE);
5594
5595         if(!NT_STATUS_IS_OK(status)) {
5596                 reply_nterror(req, status);
5597                 END_PROFILE(SMBsplclose);
5598                 return;
5599         }
5600
5601         reply_outbuf(req, 0, 0);
5602
5603         END_PROFILE(SMBsplclose);
5604         return;
5605 }
5606
5607 /****************************************************************************
5608  Reply to a printqueue.
5609 ****************************************************************************/
5610
5611 void reply_printqueue(struct smb_request *req)
5612 {
5613         connection_struct *conn = req->conn;
5614         int max_count;
5615         int start_index;
5616
5617         START_PROFILE(SMBsplretq);
5618
5619         if (req->wct < 2) {
5620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5621                 END_PROFILE(SMBsplretq);
5622                 return;
5623         }
5624
5625         max_count = SVAL(req->vwv+0, 0);
5626         start_index = SVAL(req->vwv+1, 0);
5627
5628         /* we used to allow the client to get the cnum wrong, but that
5629            is really quite gross and only worked when there was only
5630            one printer - I think we should now only accept it if they
5631            get it right (tridge) */
5632         if (!CAN_PRINT(conn)) {
5633                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5634                 END_PROFILE(SMBsplretq);
5635                 return;
5636         }
5637
5638         reply_outbuf(req, 2, 3);
5639         SSVAL(req->outbuf,smb_vwv0,0);
5640         SSVAL(req->outbuf,smb_vwv1,0);
5641         SCVAL(smb_buf(req->outbuf),0,1);
5642         SSVAL(smb_buf(req->outbuf),1,0);
5643
5644         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5645                  start_index, max_count));
5646
5647         {
5648                 TALLOC_CTX *mem_ctx = talloc_tos();
5649                 NTSTATUS status;
5650                 WERROR werr;
5651                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5652                 struct rpc_pipe_client *cli = NULL;
5653                 struct dcerpc_binding_handle *b = NULL;
5654                 struct policy_handle handle;
5655                 struct spoolss_DevmodeContainer devmode_ctr;
5656                 union spoolss_JobInfo *info;
5657                 uint32_t count;
5658                 uint32_t num_to_get;
5659                 uint32_t first;
5660                 uint32_t i;
5661
5662                 ZERO_STRUCT(handle);
5663
5664                 status = rpc_pipe_open_interface(conn,
5665                                                  &ndr_table_spoolss,
5666                                                  conn->session_info,
5667                                                  conn->sconn->remote_address,
5668                                                  conn->sconn->msg_ctx,
5669                                                  &cli);
5670                 if (!NT_STATUS_IS_OK(status)) {
5671                         DEBUG(0, ("reply_printqueue: "
5672                                   "could not connect to spoolss: %s\n",
5673                                   nt_errstr(status)));
5674                         reply_nterror(req, status);
5675                         goto out;
5676                 }
5677                 b = cli->binding_handle;
5678
5679                 ZERO_STRUCT(devmode_ctr);
5680
5681                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5682                                                 sharename,
5683                                                 NULL, devmode_ctr,
5684                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5685                                                 &handle,
5686                                                 &werr);
5687                 if (!NT_STATUS_IS_OK(status)) {
5688                         reply_nterror(req, status);
5689                         goto out;
5690                 }
5691                 if (!W_ERROR_IS_OK(werr)) {
5692                         reply_nterror(req, werror_to_ntstatus(werr));
5693                         goto out;
5694                 }
5695
5696                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5697                                                &handle,
5698                                                0, /* firstjob */
5699                                                0xff, /* numjobs */
5700                                                2, /* level */
5701                                                0, /* offered */
5702                                                &count,
5703                                                &info);
5704                 if (!W_ERROR_IS_OK(werr)) {
5705                         reply_nterror(req, werror_to_ntstatus(werr));
5706                         goto out;
5707                 }
5708
5709                 if (max_count > 0) {
5710                         first = start_index;
5711                 } else {
5712                         first = start_index + max_count + 1;
5713                 }
5714
5715                 if (first >= count) {
5716                         num_to_get = first;
5717                 } else {
5718                         num_to_get = first + MIN(ABS(max_count), count - first);
5719                 }
5720
5721                 for (i = first; i < num_to_get; i++) {
5722                         char blob[28];
5723                         char *p = blob;
5724                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5725                         int qstatus;
5726                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5727                                                         info[i].info2.job_id);
5728
5729                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5730                                 qstatus = 2;
5731                         } else {
5732                                 qstatus = 3;
5733                         }
5734
5735                         srv_put_dos_date2(p, 0, qtime);
5736                         SCVAL(p, 4, qstatus);
5737                         SSVAL(p, 5, qrapjobid);
5738                         SIVAL(p, 7, info[i].info2.size);
5739                         SCVAL(p, 11, 0);
5740                         srvstr_push(blob, req->flags2, p+12,
5741                                     info[i].info2.notify_name, 16, STR_ASCII);
5742
5743                         if (message_push_blob(
5744                                     &req->outbuf,
5745                                     data_blob_const(
5746                                             blob, sizeof(blob))) == -1) {
5747                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5748                                 goto out;
5749                         }
5750                 }
5751
5752                 if (count > 0) {
5753                         SSVAL(req->outbuf,smb_vwv0,count);
5754                         SSVAL(req->outbuf,smb_vwv1,
5755                               (max_count>0?first+count:first-1));
5756                         SCVAL(smb_buf(req->outbuf),0,1);
5757                         SSVAL(smb_buf(req->outbuf),1,28*count);
5758                 }
5759
5760
5761                 DEBUG(3, ("%u entries returned in queue\n",
5762                           (unsigned)count));
5763
5764 out:
5765                 if (b && is_valid_policy_hnd(&handle)) {
5766                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5767                 }
5768
5769         }
5770
5771         END_PROFILE(SMBsplretq);
5772         return;
5773 }
5774
5775 /****************************************************************************
5776  Reply to a printwrite.
5777 ****************************************************************************/
5778
5779 void reply_printwrite(struct smb_request *req)
5780 {
5781         connection_struct *conn = req->conn;
5782         int numtowrite;
5783         const char *data;
5784         files_struct *fsp;
5785
5786         START_PROFILE(SMBsplwr);
5787
5788         if (req->wct < 1) {
5789                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5790                 END_PROFILE(SMBsplwr);
5791                 return;
5792         }
5793
5794         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5795
5796         if (!check_fsp(conn, req, fsp)) {
5797                 END_PROFILE(SMBsplwr);
5798                 return;
5799         }
5800
5801         if (!fsp->print_file) {
5802                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5803                 END_PROFILE(SMBsplwr);
5804                 return;
5805         }
5806
5807         if (!CHECK_WRITE(fsp)) {
5808                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5809                 END_PROFILE(SMBsplwr);
5810                 return;
5811         }
5812
5813         numtowrite = SVAL(req->buf, 1);
5814
5815         if (req->buflen < numtowrite + 3) {
5816                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5817                 END_PROFILE(SMBsplwr);
5818                 return;
5819         }
5820
5821         data = (const char *)req->buf + 3;
5822
5823         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5824                 reply_nterror(req, map_nt_error_from_unix(errno));
5825                 END_PROFILE(SMBsplwr);
5826                 return;
5827         }
5828
5829         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5830
5831         END_PROFILE(SMBsplwr);
5832         return;
5833 }
5834
5835 /****************************************************************************
5836  Reply to a mkdir.
5837 ****************************************************************************/
5838
5839 void reply_mkdir(struct smb_request *req)
5840 {
5841         connection_struct *conn = req->conn;
5842         struct smb_filename *smb_dname = NULL;
5843         char *directory = NULL;
5844         NTSTATUS status;
5845         TALLOC_CTX *ctx = talloc_tos();
5846
5847         START_PROFILE(SMBmkdir);
5848
5849         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5850                             STR_TERMINATE, &status);
5851         if (!NT_STATUS_IS_OK(status)) {
5852                 reply_nterror(req, status);
5853                 goto out;
5854         }
5855
5856         status = filename_convert(ctx, conn,
5857                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5858                                  directory,
5859                                  UCF_PREP_CREATEFILE,
5860                                  NULL,
5861                                  &smb_dname);
5862         if (!NT_STATUS_IS_OK(status)) {
5863                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5864                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5865                                         ERRSRV, ERRbadpath);
5866                         goto out;
5867                 }
5868                 reply_nterror(req, status);
5869                 goto out;
5870         }
5871
5872         status = create_directory(conn, req, smb_dname);
5873
5874         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5875
5876         if (!NT_STATUS_IS_OK(status)) {
5877
5878                 if (!use_nt_status()
5879                     && NT_STATUS_EQUAL(status,
5880                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5881                         /*
5882                          * Yes, in the DOS error code case we get a
5883                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5884                          * samba4 torture test.
5885                          */
5886                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5887                 }
5888
5889                 reply_nterror(req, status);
5890                 goto out;
5891         }
5892
5893         reply_outbuf(req, 0, 0);
5894
5895         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5896  out:
5897         TALLOC_FREE(smb_dname);
5898         END_PROFILE(SMBmkdir);
5899         return;
5900 }
5901
5902 /****************************************************************************
5903  Reply to a rmdir.
5904 ****************************************************************************/
5905
5906 void reply_rmdir(struct smb_request *req)
5907 {
5908         connection_struct *conn = req->conn;
5909         struct smb_filename *smb_dname = NULL;
5910         char *directory = NULL;
5911         NTSTATUS status;
5912         TALLOC_CTX *ctx = talloc_tos();
5913         files_struct *fsp = NULL;
5914         int info = 0;
5915         struct smbd_server_connection *sconn = req->sconn;
5916
5917         START_PROFILE(SMBrmdir);
5918
5919         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5920                             STR_TERMINATE, &status);
5921         if (!NT_STATUS_IS_OK(status)) {
5922                 reply_nterror(req, status);
5923                 goto out;
5924         }
5925
5926         status = filename_convert(ctx, conn,
5927                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5928                                  directory,
5929                                  0,
5930                                  NULL,
5931                                  &smb_dname);
5932         if (!NT_STATUS_IS_OK(status)) {
5933                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5934                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5935                                         ERRSRV, ERRbadpath);
5936                         goto out;
5937                 }
5938                 reply_nterror(req, status);
5939                 goto out;
5940         }
5941
5942         if (is_ntfs_stream_smb_fname(smb_dname)) {
5943                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5944                 goto out;
5945         }
5946
5947         status = SMB_VFS_CREATE_FILE(
5948                 conn,                                   /* conn */
5949                 req,                                    /* req */
5950                 0,                                      /* root_dir_fid */
5951                 smb_dname,                              /* fname */
5952                 DELETE_ACCESS,                          /* access_mask */
5953                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5954                         FILE_SHARE_DELETE),
5955                 FILE_OPEN,                              /* create_disposition*/
5956                 FILE_DIRECTORY_FILE,                    /* create_options */
5957                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5958                 0,                                      /* oplock_request */
5959                 0,                                      /* allocation_size */
5960                 0,                                      /* private_flags */
5961                 NULL,                                   /* sd */
5962                 NULL,                                   /* ea_list */
5963                 &fsp,                                   /* result */
5964                 &info);                                 /* pinfo */
5965
5966         if (!NT_STATUS_IS_OK(status)) {
5967                 if (open_was_deferred(req->sconn, req->mid)) {
5968                         /* We have re-scheduled this call. */
5969                         goto out;
5970                 }
5971                 reply_nterror(req, status);
5972                 goto out;
5973         }
5974
5975         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5976         if (!NT_STATUS_IS_OK(status)) {
5977                 close_file(req, fsp, ERROR_CLOSE);
5978                 reply_nterror(req, status);
5979                 goto out;
5980         }
5981
5982         if (!set_delete_on_close(fsp, true,
5983                         conn->session_info->security_token,
5984                         conn->session_info->unix_token)) {
5985                 close_file(req, fsp, ERROR_CLOSE);
5986                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5987                 goto out;
5988         }
5989
5990         status = close_file(req, fsp, NORMAL_CLOSE);
5991         if (!NT_STATUS_IS_OK(status)) {
5992                 reply_nterror(req, status);
5993         } else {
5994                 reply_outbuf(req, 0, 0);
5995         }
5996
5997         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5998
5999         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6000  out:
6001         TALLOC_FREE(smb_dname);
6002         END_PROFILE(SMBrmdir);
6003         return;
6004 }
6005
6006 /*******************************************************************
6007  Resolve wildcards in a filename rename.
6008 ********************************************************************/
6009
6010 static bool resolve_wildcards(TALLOC_CTX *ctx,
6011                                 const char *name1,
6012                                 const char *name2,
6013                                 char **pp_newname)
6014 {
6015         char *name2_copy = NULL;
6016         char *root1 = NULL;
6017         char *root2 = NULL;
6018         char *ext1 = NULL;
6019         char *ext2 = NULL;
6020         char *p,*p2, *pname1, *pname2;
6021
6022         name2_copy = talloc_strdup(ctx, name2);
6023         if (!name2_copy) {
6024                 return False;
6025         }
6026
6027         pname1 = strrchr_m(name1,'/');
6028         pname2 = strrchr_m(name2_copy,'/');
6029
6030         if (!pname1 || !pname2) {
6031                 return False;
6032         }
6033
6034         /* Truncate the copy of name2 at the last '/' */
6035         *pname2 = '\0';
6036
6037         /* Now go past the '/' */
6038         pname1++;
6039         pname2++;
6040
6041         root1 = talloc_strdup(ctx, pname1);
6042         root2 = talloc_strdup(ctx, pname2);
6043
6044         if (!root1 || !root2) {
6045                 return False;
6046         }
6047
6048         p = strrchr_m(root1,'.');
6049         if (p) {
6050                 *p = 0;
6051                 ext1 = talloc_strdup(ctx, p+1);
6052         } else {
6053                 ext1 = talloc_strdup(ctx, "");
6054         }
6055         p = strrchr_m(root2,'.');
6056         if (p) {
6057                 *p = 0;
6058                 ext2 = talloc_strdup(ctx, p+1);
6059         } else {
6060                 ext2 = talloc_strdup(ctx, "");
6061         }
6062
6063         if (!ext1 || !ext2) {
6064                 return False;
6065         }
6066
6067         p = root1;
6068         p2 = root2;
6069         while (*p2) {
6070                 if (*p2 == '?') {
6071                         /* Hmmm. Should this be mb-aware ? */
6072                         *p2 = *p;
6073                         p2++;
6074                 } else if (*p2 == '*') {
6075                         *p2 = '\0';
6076                         root2 = talloc_asprintf(ctx, "%s%s",
6077                                                 root2,
6078                                                 p);
6079                         if (!root2) {
6080                                 return False;
6081                         }
6082                         break;
6083                 } else {
6084                         p2++;
6085                 }
6086                 if (*p) {
6087                         p++;
6088                 }
6089         }
6090
6091         p = ext1;
6092         p2 = ext2;
6093         while (*p2) {
6094                 if (*p2 == '?') {
6095                         /* Hmmm. Should this be mb-aware ? */
6096                         *p2 = *p;
6097                         p2++;
6098                 } else if (*p2 == '*') {
6099                         *p2 = '\0';
6100                         ext2 = talloc_asprintf(ctx, "%s%s",
6101                                                 ext2,
6102                                                 p);
6103                         if (!ext2) {
6104                                 return False;
6105                         }
6106                         break;
6107                 } else {
6108                         p2++;
6109                 }
6110                 if (*p) {
6111                         p++;
6112                 }
6113         }
6114
6115         if (*ext2) {
6116                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6117                                 name2_copy,
6118                                 root2,
6119                                 ext2);
6120         } else {
6121                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6122                                 name2_copy,
6123                                 root2);
6124         }
6125
6126         if (!*pp_newname) {
6127                 return False;
6128         }
6129
6130         return True;
6131 }
6132
6133 /****************************************************************************
6134  Ensure open files have their names updated. Updated to notify other smbd's
6135  asynchronously.
6136 ****************************************************************************/
6137
6138 static void rename_open_files(connection_struct *conn,
6139                               struct share_mode_lock *lck,
6140                               struct file_id id,
6141                               uint32_t orig_name_hash,
6142                               const struct smb_filename *smb_fname_dst)
6143 {
6144         files_struct *fsp;
6145         bool did_rename = False;
6146         NTSTATUS status;
6147         uint32_t new_name_hash = 0;
6148
6149         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6150             fsp = file_find_di_next(fsp)) {
6151                 /* fsp_name is a relative path under the fsp. To change this for other
6152                    sharepaths we need to manipulate relative paths. */
6153                 /* TODO - create the absolute path and manipulate the newname
6154                    relative to the sharepath. */
6155                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6156                         continue;
6157                 }
6158                 if (fsp->name_hash != orig_name_hash) {
6159                         continue;
6160                 }
6161                 DEBUG(10, ("rename_open_files: renaming file %s "
6162                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6163                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6164                            smb_fname_str_dbg(smb_fname_dst)));
6165
6166                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6167                 if (NT_STATUS_IS_OK(status)) {
6168                         did_rename = True;
6169                         new_name_hash = fsp->name_hash;
6170                 }
6171         }
6172
6173         if (!did_rename) {
6174                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6175                            "for %s\n", file_id_string_tos(&id),
6176                            smb_fname_str_dbg(smb_fname_dst)));
6177         }
6178
6179         /* Send messages to all smbd's (not ourself) that the name has changed. */
6180         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6181                               orig_name_hash, new_name_hash,
6182                               smb_fname_dst);
6183
6184 }
6185
6186 /****************************************************************************
6187  We need to check if the source path is a parent directory of the destination
6188  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6189  refuse the rename with a sharing violation. Under UNIX the above call can
6190  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6191  probably need to check that the client is a Windows one before disallowing
6192  this as a UNIX client (one with UNIX extensions) can know the source is a
6193  symlink and make this decision intelligently. Found by an excellent bug
6194  report from <AndyLiebman@aol.com>.
6195 ****************************************************************************/
6196
6197 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6198                                      const struct smb_filename *smb_fname_dst)
6199 {
6200         const char *psrc = smb_fname_src->base_name;
6201         const char *pdst = smb_fname_dst->base_name;
6202         size_t slen;
6203
6204         if (psrc[0] == '.' && psrc[1] == '/') {
6205                 psrc += 2;
6206         }
6207         if (pdst[0] == '.' && pdst[1] == '/') {
6208                 pdst += 2;
6209         }
6210         if ((slen = strlen(psrc)) > strlen(pdst)) {
6211                 return False;
6212         }
6213         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6214 }
6215
6216 /*
6217  * Do the notify calls from a rename
6218  */
6219
6220 static void notify_rename(connection_struct *conn, bool is_dir,
6221                           const struct smb_filename *smb_fname_src,
6222                           const struct smb_filename *smb_fname_dst)
6223 {
6224         char *parent_dir_src = NULL;
6225         char *parent_dir_dst = NULL;
6226         uint32 mask;
6227
6228         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6229                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6230
6231         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6232                             &parent_dir_src, NULL) ||
6233             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6234                             &parent_dir_dst, NULL)) {
6235                 goto out;
6236         }
6237
6238         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6239                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6240                              smb_fname_src->base_name);
6241                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6242                              smb_fname_dst->base_name);
6243         }
6244         else {
6245                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6246                              smb_fname_src->base_name);
6247                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6248                              smb_fname_dst->base_name);
6249         }
6250
6251         /* this is a strange one. w2k3 gives an additional event for
6252            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6253            files, but not directories */
6254         if (!is_dir) {
6255                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6256                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6257                              |FILE_NOTIFY_CHANGE_CREATION,
6258                              smb_fname_dst->base_name);
6259         }
6260  out:
6261         TALLOC_FREE(parent_dir_src);
6262         TALLOC_FREE(parent_dir_dst);
6263 }
6264
6265 /****************************************************************************
6266  Returns an error if the parent directory for a filename is open in an
6267  incompatible way.
6268 ****************************************************************************/
6269
6270 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6271                                         const struct smb_filename *smb_fname_dst_in)
6272 {
6273         char *parent_dir = NULL;
6274         struct smb_filename smb_fname_parent;
6275         struct file_id id;
6276         files_struct *fsp = NULL;
6277         int ret;
6278
6279         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6280                         &parent_dir, NULL)) {
6281                 return NT_STATUS_NO_MEMORY;
6282         }
6283         ZERO_STRUCT(smb_fname_parent);
6284         smb_fname_parent.base_name = parent_dir;
6285
6286         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6287         if (ret == -1) {
6288                 return map_nt_error_from_unix(errno);
6289         }
6290
6291         /*
6292          * We're only checking on this smbd here, mostly good
6293          * enough.. and will pass tests.
6294          */
6295
6296         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6297         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6298                         fsp = file_find_di_next(fsp)) {
6299                 if (fsp->access_mask & DELETE_ACCESS) {
6300                         return NT_STATUS_SHARING_VIOLATION;
6301                 }
6302         }
6303         return NT_STATUS_OK;
6304 }
6305
6306 /****************************************************************************
6307  Rename an open file - given an fsp.
6308 ****************************************************************************/
6309
6310 NTSTATUS rename_internals_fsp(connection_struct *conn,
6311                         files_struct *fsp,
6312                         const struct smb_filename *smb_fname_dst_in,
6313                         uint32 attrs,
6314                         bool replace_if_exists)
6315 {
6316         TALLOC_CTX *ctx = talloc_tos();
6317         struct smb_filename *smb_fname_dst = NULL;
6318         NTSTATUS status = NT_STATUS_OK;
6319         struct share_mode_lock *lck = NULL;
6320         bool dst_exists, old_is_stream, new_is_stream;
6321
6322         status = check_name(conn, smb_fname_dst_in->base_name);
6323         if (!NT_STATUS_IS_OK(status)) {
6324                 return status;
6325         }
6326
6327         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6328         if (!NT_STATUS_IS_OK(status)) {
6329                 return status;
6330         }
6331
6332         /* Make a copy of the dst smb_fname structs */
6333
6334         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6335         if (smb_fname_dst == NULL) {
6336                 status = NT_STATUS_NO_MEMORY;
6337                 goto out;
6338         }
6339
6340         /*
6341          * Check for special case with case preserving and not
6342          * case sensitive. If the old last component differs from the original
6343          * last component only by case, then we should allow
6344          * the rename (user is trying to change the case of the
6345          * filename).
6346          */
6347         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6348             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6349             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6350                 char *last_slash;
6351                 char *fname_dst_lcomp_base_mod = NULL;
6352                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6353
6354                 /*
6355                  * Get the last component of the destination name.
6356                  */
6357                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6358                 if (last_slash) {
6359                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6360                 } else {
6361                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6362                 }
6363                 if (!fname_dst_lcomp_base_mod) {
6364                         status = NT_STATUS_NO_MEMORY;
6365                         goto out;
6366                 }
6367
6368                 /*
6369                  * Create an smb_filename struct using the original last
6370                  * component of the destination.
6371                  */
6372                 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6373                         ctx, smb_fname_dst->original_lcomp, NULL);
6374                 if (smb_fname_orig_lcomp == NULL) {
6375                         status = NT_STATUS_NO_MEMORY;
6376                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6377                         goto out;
6378                 }
6379
6380                 /* If the base names only differ by case, use original. */
6381                 if(!strcsequal(fname_dst_lcomp_base_mod,
6382                                smb_fname_orig_lcomp->base_name)) {
6383                         char *tmp;
6384                         /*
6385                          * Replace the modified last component with the
6386                          * original.
6387                          */
6388                         if (last_slash) {
6389                                 *last_slash = '\0'; /* Truncate at the '/' */
6390                                 tmp = talloc_asprintf(smb_fname_dst,
6391                                         "%s/%s",
6392                                         smb_fname_dst->base_name,
6393                                         smb_fname_orig_lcomp->base_name);
6394                         } else {
6395                                 tmp = talloc_asprintf(smb_fname_dst,
6396                                         "%s",
6397                                         smb_fname_orig_lcomp->base_name);
6398                         }
6399                         if (tmp == NULL) {
6400                                 status = NT_STATUS_NO_MEMORY;
6401                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6402                                 TALLOC_FREE(smb_fname_orig_lcomp);
6403                                 goto out;
6404                         }
6405                         TALLOC_FREE(smb_fname_dst->base_name);
6406                         smb_fname_dst->base_name = tmp;
6407                 }
6408
6409                 /* If the stream_names only differ by case, use original. */
6410                 if(!strcsequal(smb_fname_dst->stream_name,
6411                                smb_fname_orig_lcomp->stream_name)) {
6412                         char *tmp = NULL;
6413                         /* Use the original stream. */
6414                         tmp = talloc_strdup(smb_fname_dst,
6415                                             smb_fname_orig_lcomp->stream_name);
6416                         if (tmp == NULL) {
6417                                 status = NT_STATUS_NO_MEMORY;
6418                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6419                                 TALLOC_FREE(smb_fname_orig_lcomp);
6420                                 goto out;
6421                         }
6422                         TALLOC_FREE(smb_fname_dst->stream_name);
6423                         smb_fname_dst->stream_name = tmp;
6424                 }
6425                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6426                 TALLOC_FREE(smb_fname_orig_lcomp);
6427         }
6428
6429         /*
6430          * If the src and dest names are identical - including case,
6431          * don't do the rename, just return success.
6432          */
6433
6434         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6435             strcsequal(fsp->fsp_name->stream_name,
6436                        smb_fname_dst->stream_name)) {
6437                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6438                           "- returning success\n",
6439                           smb_fname_str_dbg(smb_fname_dst)));
6440                 status = NT_STATUS_OK;
6441                 goto out;
6442         }
6443
6444         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6445         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6446
6447         /* Return the correct error code if both names aren't streams. */
6448         if (!old_is_stream && new_is_stream) {
6449                 status = NT_STATUS_OBJECT_NAME_INVALID;
6450                 goto out;
6451         }
6452
6453         if (old_is_stream && !new_is_stream) {
6454                 status = NT_STATUS_INVALID_PARAMETER;
6455                 goto out;
6456         }
6457
6458         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6459
6460         if(!replace_if_exists && dst_exists) {
6461                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6462                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6463                           smb_fname_str_dbg(smb_fname_dst)));
6464                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6465                 goto out;
6466         }
6467
6468         if (dst_exists) {
6469                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6470                     &smb_fname_dst->st);
6471                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6472                                                            fileid);
6473                 /* The file can be open when renaming a stream */
6474                 if (dst_fsp && !new_is_stream) {
6475                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6476                         status = NT_STATUS_ACCESS_DENIED;
6477                         goto out;
6478                 }
6479         }
6480
6481         /* Ensure we have a valid stat struct for the source. */
6482         status = vfs_stat_fsp(fsp);
6483         if (!NT_STATUS_IS_OK(status)) {
6484                 goto out;
6485         }
6486
6487         status = can_rename(conn, fsp, attrs);
6488
6489         if (!NT_STATUS_IS_OK(status)) {
6490                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6491                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6492                           smb_fname_str_dbg(smb_fname_dst)));
6493                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6494                         status = NT_STATUS_ACCESS_DENIED;
6495                 goto out;
6496         }
6497
6498         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6499                 status = NT_STATUS_ACCESS_DENIED;
6500         }
6501
6502         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6503
6504         /*
6505          * We have the file open ourselves, so not being able to get the
6506          * corresponding share mode lock is a fatal error.
6507          */
6508
6509         SMB_ASSERT(lck != NULL);
6510
6511         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6512                 uint32 create_options = fsp->fh->private_options;
6513
6514                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6515                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6516                           smb_fname_str_dbg(smb_fname_dst)));
6517
6518                 if (!fsp->is_directory &&
6519                     !lp_posix_pathnames() &&
6520                     (lp_map_archive(SNUM(conn)) ||
6521                     lp_store_dos_attributes(SNUM(conn)))) {
6522                         /* We must set the archive bit on the newly
6523                            renamed file. */
6524                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6525                                 uint32_t old_dosmode = dos_mode(conn,
6526                                                         smb_fname_dst);
6527                                 file_set_dosmode(conn,
6528                                         smb_fname_dst,
6529                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6530                                         NULL,
6531                                         true);
6532                         }
6533                 }
6534
6535                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6536                               smb_fname_dst);
6537
6538                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6539                                   smb_fname_dst);
6540
6541                 /*
6542                  * A rename acts as a new file create w.r.t. allowing an initial delete
6543                  * on close, probably because in Windows there is a new handle to the
6544                  * new file. If initial delete on close was requested but not
6545                  * originally set, we need to set it here. This is probably not 100% correct,
6546                  * but will work for the CIFSFS client which in non-posix mode
6547                  * depends on these semantics. JRA.
6548                  */
6549
6550                 if (create_options & FILE_DELETE_ON_CLOSE) {
6551                         status = can_set_delete_on_close(fsp, 0);
6552
6553                         if (NT_STATUS_IS_OK(status)) {
6554                                 /* Note that here we set the *inital* delete on close flag,
6555                                  * not the regular one. The magic gets handled in close. */
6556                                 fsp->initial_delete_on_close = True;
6557                         }
6558                 }
6559                 TALLOC_FREE(lck);
6560                 status = NT_STATUS_OK;
6561                 goto out;
6562         }
6563
6564         TALLOC_FREE(lck);
6565
6566         if (errno == ENOTDIR || errno == EISDIR) {
6567                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6568         } else {
6569                 status = map_nt_error_from_unix(errno);
6570         }
6571
6572         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6573                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6574                   smb_fname_str_dbg(smb_fname_dst)));
6575
6576  out:
6577         TALLOC_FREE(smb_fname_dst);
6578
6579         return status;
6580 }
6581
6582 /****************************************************************************
6583  The guts of the rename command, split out so it may be called by the NT SMB
6584  code.
6585 ****************************************************************************/
6586
6587 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6588                         connection_struct *conn,
6589                         struct smb_request *req,
6590                         struct smb_filename *smb_fname_src,
6591                         struct smb_filename *smb_fname_dst,
6592                         uint32 attrs,
6593                         bool replace_if_exists,
6594                         bool src_has_wild,
6595                         bool dest_has_wild,
6596                         uint32_t access_mask)
6597 {
6598         char *fname_src_dir = NULL;
6599         char *fname_src_mask = NULL;
6600         int count=0;
6601         NTSTATUS status = NT_STATUS_OK;
6602         struct smb_Dir *dir_hnd = NULL;
6603         const char *dname = NULL;
6604         char *talloced = NULL;
6605         long offset = 0;
6606         int create_options = 0;
6607         bool posix_pathnames = lp_posix_pathnames();
6608         int rc;
6609
6610         /*
6611          * Split the old name into directory and last component
6612          * strings. Note that unix_convert may have stripped off a
6613          * leading ./ from both name and newname if the rename is
6614          * at the root of the share. We need to make sure either both
6615          * name and newname contain a / character or neither of them do
6616          * as this is checked in resolve_wildcards().
6617          */
6618
6619         /* Split up the directory from the filename/mask. */
6620         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6621                                       &fname_src_dir, &fname_src_mask);
6622         if (!NT_STATUS_IS_OK(status)) {
6623                 status = NT_STATUS_NO_MEMORY;
6624                 goto out;
6625         }
6626
6627         /*
6628          * We should only check the mangled cache
6629          * here if unix_convert failed. This means
6630          * that the path in 'mask' doesn't exist
6631          * on the file system and so we need to look
6632          * for a possible mangle. This patch from
6633          * Tine Smukavec <valentin.smukavec@hermes.si>.
6634          */
6635
6636         if (!VALID_STAT(smb_fname_src->st) &&
6637             mangle_is_mangled(fname_src_mask, conn->params)) {
6638                 char *new_mask = NULL;
6639                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6640                                             conn->params);
6641                 if (new_mask) {
6642                         TALLOC_FREE(fname_src_mask);
6643                         fname_src_mask = new_mask;
6644                 }
6645         }
6646
6647         if (!src_has_wild) {
6648                 files_struct *fsp;
6649
6650                 /*
6651                  * Only one file needs to be renamed. Append the mask back
6652                  * onto the directory.
6653                  */
6654                 TALLOC_FREE(smb_fname_src->base_name);
6655                 if (ISDOT(fname_src_dir)) {
6656                         /* Ensure we use canonical names on open. */
6657                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6658                                                         "%s",
6659                                                         fname_src_mask);
6660                 } else {
6661                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6662                                                         "%s/%s",
6663                                                         fname_src_dir,
6664                                                         fname_src_mask);
6665                 }
6666                 if (!smb_fname_src->base_name) {
6667                         status = NT_STATUS_NO_MEMORY;
6668                         goto out;
6669                 }
6670
6671                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6672                           "case_preserve = %d, short case preserve = %d, "
6673                           "directory = %s, newname = %s, "
6674                           "last_component_dest = %s\n",
6675                           conn->case_sensitive, conn->case_preserve,
6676                           conn->short_case_preserve,
6677                           smb_fname_str_dbg(smb_fname_src),
6678                           smb_fname_str_dbg(smb_fname_dst),
6679                           smb_fname_dst->original_lcomp));
6680
6681                 /* The dest name still may have wildcards. */
6682                 if (dest_has_wild) {
6683                         char *fname_dst_mod = NULL;
6684                         if (!resolve_wildcards(smb_fname_dst,
6685                                                smb_fname_src->base_name,
6686                                                smb_fname_dst->base_name,
6687                                                &fname_dst_mod)) {
6688                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6689                                           "%s %s failed\n",
6690                                           smb_fname_src->base_name,
6691                                           smb_fname_dst->base_name));
6692                                 status = NT_STATUS_NO_MEMORY;
6693                                 goto out;
6694                         }
6695                         TALLOC_FREE(smb_fname_dst->base_name);
6696                         smb_fname_dst->base_name = fname_dst_mod;
6697                 }
6698
6699                 ZERO_STRUCT(smb_fname_src->st);
6700                 if (posix_pathnames) {
6701                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6702                 } else {
6703                         rc = SMB_VFS_STAT(conn, smb_fname_src);
6704                 }
6705                 if (rc == -1) {
6706                         status = map_nt_error_from_unix_common(errno);
6707                         goto out;
6708                 }
6709
6710                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6711                         create_options |= FILE_DIRECTORY_FILE;
6712                 }
6713
6714                 status = SMB_VFS_CREATE_FILE(
6715                         conn,                           /* conn */
6716                         req,                            /* req */
6717                         0,                              /* root_dir_fid */
6718                         smb_fname_src,                  /* fname */
6719                         access_mask,                    /* access_mask */
6720                         (FILE_SHARE_READ |              /* share_access */
6721                             FILE_SHARE_WRITE),
6722                         FILE_OPEN,                      /* create_disposition*/
6723                         create_options,                 /* create_options */
6724                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6725                         0,                              /* oplock_request */
6726                         0,                              /* allocation_size */
6727                         0,                              /* private_flags */
6728                         NULL,                           /* sd */
6729                         NULL,                           /* ea_list */
6730                         &fsp,                           /* result */
6731                         NULL);                          /* pinfo */
6732
6733                 if (!NT_STATUS_IS_OK(status)) {
6734                         DEBUG(3, ("Could not open rename source %s: %s\n",
6735                                   smb_fname_str_dbg(smb_fname_src),
6736                                   nt_errstr(status)));
6737                         goto out;
6738                 }
6739
6740                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6741                                               attrs, replace_if_exists);
6742
6743                 close_file(req, fsp, NORMAL_CLOSE);
6744
6745                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6746                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6747                           smb_fname_str_dbg(smb_fname_dst)));
6748
6749                 goto out;
6750         }
6751
6752         /*
6753          * Wildcards - process each file that matches.
6754          */
6755         if (strequal(fname_src_mask, "????????.???")) {
6756                 TALLOC_FREE(fname_src_mask);
6757                 fname_src_mask = talloc_strdup(ctx, "*");
6758                 if (!fname_src_mask) {
6759                         status = NT_STATUS_NO_MEMORY;
6760                         goto out;
6761                 }
6762         }
6763
6764         status = check_name(conn, fname_src_dir);
6765         if (!NT_STATUS_IS_OK(status)) {
6766                 goto out;
6767         }
6768
6769         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6770                           attrs);
6771         if (dir_hnd == NULL) {
6772                 status = map_nt_error_from_unix(errno);
6773                 goto out;
6774         }
6775
6776         status = NT_STATUS_NO_SUCH_FILE;
6777         /*
6778          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6779          * - gentest fix. JRA
6780          */
6781
6782         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6783                                     &talloced))) {
6784                 files_struct *fsp = NULL;
6785                 char *destname = NULL;
6786                 bool sysdir_entry = False;
6787
6788                 /* Quick check for "." and ".." */
6789                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6790                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6791                                 sysdir_entry = True;
6792                         } else {
6793                                 TALLOC_FREE(talloced);
6794                                 continue;
6795                         }
6796                 }
6797
6798                 if (!is_visible_file(conn, fname_src_dir, dname,
6799                                      &smb_fname_src->st, false)) {
6800                         TALLOC_FREE(talloced);
6801                         continue;
6802                 }
6803
6804                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6805                         TALLOC_FREE(talloced);
6806                         continue;
6807                 }
6808
6809                 if (sysdir_entry) {
6810                         status = NT_STATUS_OBJECT_NAME_INVALID;
6811                         break;
6812                 }
6813
6814                 TALLOC_FREE(smb_fname_src->base_name);
6815                 if (ISDOT(fname_src_dir)) {
6816                         /* Ensure we use canonical names on open. */
6817                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6818                                                         "%s",
6819                                                         dname);
6820                 } else {
6821                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6822                                                         "%s/%s",
6823                                                         fname_src_dir,
6824                                                         dname);
6825                 }
6826                 if (!smb_fname_src->base_name) {
6827                         status = NT_STATUS_NO_MEMORY;
6828                         goto out;
6829                 }
6830
6831                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6832                                        smb_fname_dst->base_name,
6833                                        &destname)) {
6834                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6835                                   smb_fname_src->base_name, destname));
6836                         TALLOC_FREE(talloced);
6837                         continue;
6838                 }
6839                 if (!destname) {
6840                         status = NT_STATUS_NO_MEMORY;
6841                         goto out;
6842                 }
6843
6844                 TALLOC_FREE(smb_fname_dst->base_name);
6845                 smb_fname_dst->base_name = destname;
6846
6847                 ZERO_STRUCT(smb_fname_src->st);
6848                 if (posix_pathnames) {
6849                         SMB_VFS_LSTAT(conn, smb_fname_src);
6850                 } else {
6851                         SMB_VFS_STAT(conn, smb_fname_src);
6852                 }
6853
6854                 create_options = 0;
6855
6856                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6857                         create_options |= FILE_DIRECTORY_FILE;
6858                 }
6859
6860                 status = SMB_VFS_CREATE_FILE(
6861                         conn,                           /* conn */
6862                         req,                            /* req */
6863                         0,                              /* root_dir_fid */
6864                         smb_fname_src,                  /* fname */
6865                         access_mask,                    /* access_mask */
6866                         (FILE_SHARE_READ |              /* share_access */
6867                             FILE_SHARE_WRITE),
6868                         FILE_OPEN,                      /* create_disposition*/
6869                         create_options,                 /* create_options */
6870                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6871                         0,                              /* oplock_request */
6872                         0,                              /* allocation_size */
6873                         0,                              /* private_flags */
6874                         NULL,                           /* sd */
6875                         NULL,                           /* ea_list */
6876                         &fsp,                           /* result */
6877                         NULL);                          /* pinfo */
6878
6879                 if (!NT_STATUS_IS_OK(status)) {
6880                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6881                                  "returned %s rename %s -> %s\n",
6882                                  nt_errstr(status),
6883                                  smb_fname_str_dbg(smb_fname_src),
6884                                  smb_fname_str_dbg(smb_fname_dst)));
6885                         break;
6886                 }
6887
6888                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6889                                                               dname);
6890                 if (!smb_fname_dst->original_lcomp) {
6891                         status = NT_STATUS_NO_MEMORY;
6892                         goto out;
6893                 }
6894
6895                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6896                                               attrs, replace_if_exists);
6897
6898                 close_file(req, fsp, NORMAL_CLOSE);
6899
6900                 if (!NT_STATUS_IS_OK(status)) {
6901                         DEBUG(3, ("rename_internals_fsp returned %s for "
6902                                   "rename %s -> %s\n", nt_errstr(status),
6903                                   smb_fname_str_dbg(smb_fname_src),
6904                                   smb_fname_str_dbg(smb_fname_dst)));
6905                         break;
6906                 }
6907
6908                 count++;
6909
6910                 DEBUG(3,("rename_internals: doing rename on %s -> "
6911                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6912                          smb_fname_str_dbg(smb_fname_src)));
6913                 TALLOC_FREE(talloced);
6914         }
6915         TALLOC_FREE(dir_hnd);
6916
6917         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6918                 status = map_nt_error_from_unix(errno);
6919         }
6920
6921  out:
6922         TALLOC_FREE(talloced);
6923         TALLOC_FREE(fname_src_dir);
6924         TALLOC_FREE(fname_src_mask);
6925         return status;
6926 }
6927
6928 /****************************************************************************
6929  Reply to a mv.
6930 ****************************************************************************/
6931
6932 void reply_mv(struct smb_request *req)
6933 {
6934         connection_struct *conn = req->conn;
6935         char *name = NULL;
6936         char *newname = NULL;
6937         const char *p;
6938         uint32 attrs;
6939         NTSTATUS status;
6940         bool src_has_wcard = False;
6941         bool dest_has_wcard = False;
6942         TALLOC_CTX *ctx = talloc_tos();
6943         struct smb_filename *smb_fname_src = NULL;
6944         struct smb_filename *smb_fname_dst = NULL;
6945         uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6946         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6947         bool stream_rename = false;
6948
6949         START_PROFILE(SMBmv);
6950
6951         if (req->wct < 1) {
6952                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6953                 goto out;
6954         }
6955
6956         attrs = SVAL(req->vwv+0, 0);
6957
6958         p = (const char *)req->buf + 1;
6959         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6960                                        &status, &src_has_wcard);
6961         if (!NT_STATUS_IS_OK(status)) {
6962                 reply_nterror(req, status);
6963                 goto out;
6964         }
6965         p++;
6966         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6967                                        &status, &dest_has_wcard);
6968         if (!NT_STATUS_IS_OK(status)) {
6969                 reply_nterror(req, status);
6970                 goto out;
6971         }
6972
6973         if (!lp_posix_pathnames()) {
6974                 /* The newname must begin with a ':' if the
6975                    name contains a ':'. */
6976                 if (strchr_m(name, ':')) {
6977                         if (newname[0] != ':') {
6978                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6979                                 goto out;
6980                         }
6981                         stream_rename = true;
6982                 }
6983         }
6984
6985         status = filename_convert(ctx,
6986                                   conn,
6987                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6988                                   name,
6989                                   src_ucf_flags,
6990                                   &src_has_wcard,
6991                                   &smb_fname_src);
6992
6993         if (!NT_STATUS_IS_OK(status)) {
6994                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6995                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6996                                         ERRSRV, ERRbadpath);
6997                         goto out;
6998                 }
6999                 reply_nterror(req, status);
7000                 goto out;
7001         }
7002
7003         status = filename_convert(ctx,
7004                                   conn,
7005                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7006                                   newname,
7007                                   dst_ucf_flags,
7008                                   &dest_has_wcard,
7009                                   &smb_fname_dst);
7010
7011         if (!NT_STATUS_IS_OK(status)) {
7012                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7013                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7014                                         ERRSRV, ERRbadpath);
7015                         goto out;
7016                 }
7017                 reply_nterror(req, status);
7018                 goto out;
7019         }
7020
7021         if (stream_rename) {
7022                 /* smb_fname_dst->base_name must be the same as
7023                    smb_fname_src->base_name. */
7024                 TALLOC_FREE(smb_fname_dst->base_name);
7025                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7026                                                 smb_fname_src->base_name);
7027                 if (!smb_fname_dst->base_name) {
7028                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7029                         goto out;
7030                 }
7031         }
7032
7033         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7034                  smb_fname_str_dbg(smb_fname_dst)));
7035
7036         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7037                                   attrs, False, src_has_wcard, dest_has_wcard,
7038                                   DELETE_ACCESS);
7039         if (!NT_STATUS_IS_OK(status)) {
7040                 if (open_was_deferred(req->sconn, req->mid)) {
7041                         /* We have re-scheduled this call. */
7042                         goto out;
7043                 }
7044                 reply_nterror(req, status);
7045                 goto out;
7046         }
7047
7048         reply_outbuf(req, 0, 0);
7049  out:
7050         TALLOC_FREE(smb_fname_src);
7051         TALLOC_FREE(smb_fname_dst);
7052         END_PROFILE(SMBmv);
7053         return;
7054 }
7055
7056 /*******************************************************************
7057  Copy a file as part of a reply_copy.
7058 ******************************************************************/
7059
7060 /*
7061  * TODO: check error codes on all callers
7062  */
7063
7064 NTSTATUS copy_file(TALLOC_CTX *ctx,
7065                         connection_struct *conn,
7066                         struct smb_filename *smb_fname_src,
7067                         struct smb_filename *smb_fname_dst,
7068                         int ofun,
7069                         int count,
7070                         bool target_is_directory)
7071 {
7072         struct smb_filename *smb_fname_dst_tmp = NULL;
7073         off_t ret=-1;
7074         files_struct *fsp1,*fsp2;
7075         uint32 dosattrs;
7076         uint32 new_create_disposition;
7077         NTSTATUS status;
7078
7079
7080         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7081         if (smb_fname_dst_tmp == NULL) {
7082                 return NT_STATUS_NO_MEMORY;
7083         }
7084
7085         /*
7086          * If the target is a directory, extract the last component from the
7087          * src filename and append it to the dst filename
7088          */
7089         if (target_is_directory) {
7090                 const char *p;
7091
7092                 /* dest/target can't be a stream if it's a directory. */
7093                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7094
7095                 p = strrchr_m(smb_fname_src->base_name,'/');
7096                 if (p) {
7097                         p++;
7098                 } else {
7099                         p = smb_fname_src->base_name;
7100                 }
7101                 smb_fname_dst_tmp->base_name =
7102                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7103                                            p);
7104                 if (!smb_fname_dst_tmp->base_name) {
7105                         status = NT_STATUS_NO_MEMORY;
7106                         goto out;
7107                 }
7108         }
7109
7110         status = vfs_file_exist(conn, smb_fname_src);
7111         if (!NT_STATUS_IS_OK(status)) {
7112                 goto out;
7113         }
7114
7115         if (!target_is_directory && count) {
7116                 new_create_disposition = FILE_OPEN;
7117         } else {
7118                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7119                                                  0, ofun,
7120                                                  NULL, NULL,
7121                                                  &new_create_disposition,
7122                                                  NULL,
7123                                                  NULL)) {
7124                         status = NT_STATUS_INVALID_PARAMETER;
7125                         goto out;
7126                 }
7127         }
7128
7129         /* Open the src file for reading. */
7130         status = SMB_VFS_CREATE_FILE(
7131                 conn,                                   /* conn */
7132                 NULL,                                   /* req */
7133                 0,                                      /* root_dir_fid */
7134                 smb_fname_src,                          /* fname */
7135                 FILE_GENERIC_READ,                      /* access_mask */
7136                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7137                 FILE_OPEN,                              /* create_disposition*/
7138                 0,                                      /* create_options */
7139                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7140                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7141                 0,                                      /* allocation_size */
7142                 0,                                      /* private_flags */
7143                 NULL,                                   /* sd */
7144                 NULL,                                   /* ea_list */
7145                 &fsp1,                                  /* result */
7146                 NULL);                                  /* psbuf */
7147
7148         if (!NT_STATUS_IS_OK(status)) {
7149                 goto out;
7150         }
7151
7152         dosattrs = dos_mode(conn, smb_fname_src);
7153
7154         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7155                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7156         }
7157
7158         /* Open the dst file for writing. */
7159         status = SMB_VFS_CREATE_FILE(
7160                 conn,                                   /* conn */
7161                 NULL,                                   /* req */
7162                 0,                                      /* root_dir_fid */
7163                 smb_fname_dst,                          /* fname */
7164                 FILE_GENERIC_WRITE,                     /* access_mask */
7165                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7166                 new_create_disposition,                 /* create_disposition*/
7167                 0,                                      /* create_options */
7168                 dosattrs,                               /* file_attributes */
7169                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7170                 0,                                      /* allocation_size */
7171                 0,                                      /* private_flags */
7172                 NULL,                                   /* sd */
7173                 NULL,                                   /* ea_list */
7174                 &fsp2,                                  /* result */
7175                 NULL);                                  /* psbuf */
7176
7177         if (!NT_STATUS_IS_OK(status)) {
7178                 close_file(NULL, fsp1, ERROR_CLOSE);
7179                 goto out;
7180         }
7181
7182         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7183                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7184                 if (ret == -1) {
7185                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7186                                 strerror(errno)));
7187                         status = map_nt_error_from_unix(errno);
7188                         close_file(NULL, fsp1, ERROR_CLOSE);
7189                         close_file(NULL, fsp2, ERROR_CLOSE);
7190                         goto out;
7191                 }
7192         }
7193
7194         /* Do the actual copy. */
7195         if (smb_fname_src->st.st_ex_size) {
7196                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7197         } else {
7198                 ret = 0;
7199         }
7200
7201         close_file(NULL, fsp1, NORMAL_CLOSE);
7202
7203         /* Ensure the modtime is set correctly on the destination file. */
7204         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7205
7206         /*
7207          * As we are opening fsp1 read-only we only expect
7208          * an error on close on fsp2 if we are out of space.
7209          * Thus we don't look at the error return from the
7210          * close of fsp1.
7211          */
7212         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7213
7214         if (!NT_STATUS_IS_OK(status)) {
7215                 goto out;
7216         }
7217
7218         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7219                 status = NT_STATUS_DISK_FULL;
7220                 goto out;
7221         }
7222
7223         status = NT_STATUS_OK;
7224
7225  out:
7226         TALLOC_FREE(smb_fname_dst_tmp);
7227         return status;
7228 }
7229
7230 /****************************************************************************
7231  Reply to a file copy.
7232 ****************************************************************************/
7233
7234 void reply_copy(struct smb_request *req)
7235 {
7236         connection_struct *conn = req->conn;
7237         struct smb_filename *smb_fname_src = NULL;
7238         struct smb_filename *smb_fname_dst = NULL;
7239         char *fname_src = NULL;
7240         char *fname_dst = NULL;
7241         char *fname_src_mask = NULL;
7242         char *fname_src_dir = NULL;
7243         const char *p;
7244         int count=0;
7245         int error = ERRnoaccess;
7246         int tid2;
7247         int ofun;
7248         int flags;
7249         bool target_is_directory=False;
7250         bool source_has_wild = False;
7251         bool dest_has_wild = False;
7252         NTSTATUS status;
7253         TALLOC_CTX *ctx = talloc_tos();
7254
7255         START_PROFILE(SMBcopy);
7256
7257         if (req->wct < 3) {
7258                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7259                 goto out;
7260         }
7261
7262         tid2 = SVAL(req->vwv+0, 0);
7263         ofun = SVAL(req->vwv+1, 0);
7264         flags = SVAL(req->vwv+2, 0);
7265
7266         p = (const char *)req->buf;
7267         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7268                                        &status, &source_has_wild);
7269         if (!NT_STATUS_IS_OK(status)) {
7270                 reply_nterror(req, status);
7271                 goto out;
7272         }
7273         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7274                                        &status, &dest_has_wild);
7275         if (!NT_STATUS_IS_OK(status)) {
7276                 reply_nterror(req, status);
7277                 goto out;
7278         }
7279
7280         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7281
7282         if (tid2 != conn->cnum) {
7283                 /* can't currently handle inter share copies XXXX */
7284                 DEBUG(3,("Rejecting inter-share copy\n"));
7285                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7286                 goto out;
7287         }
7288
7289         status = filename_convert(ctx, conn,
7290                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7291                                   fname_src,
7292                                   UCF_COND_ALLOW_WCARD_LCOMP,
7293                                   &source_has_wild,
7294                                   &smb_fname_src);
7295         if (!NT_STATUS_IS_OK(status)) {
7296                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7297                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7298                                         ERRSRV, ERRbadpath);
7299                         goto out;
7300                 }
7301                 reply_nterror(req, status);
7302                 goto out;
7303         }
7304
7305         status = filename_convert(ctx, conn,
7306                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7307                                   fname_dst,
7308                                   UCF_COND_ALLOW_WCARD_LCOMP,
7309                                   &dest_has_wild,
7310                                   &smb_fname_dst);
7311         if (!NT_STATUS_IS_OK(status)) {
7312                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7313                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7314                                         ERRSRV, ERRbadpath);
7315                         goto out;
7316                 }
7317                 reply_nterror(req, status);
7318                 goto out;
7319         }
7320
7321         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7322
7323         if ((flags&1) && target_is_directory) {
7324                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7325                 goto out;
7326         }
7327
7328         if ((flags&2) && !target_is_directory) {
7329                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7330                 goto out;
7331         }
7332
7333         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7334                 /* wants a tree copy! XXXX */
7335                 DEBUG(3,("Rejecting tree copy\n"));
7336                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7337                 goto out;
7338         }
7339
7340         /* Split up the directory from the filename/mask. */
7341         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7342                                       &fname_src_dir, &fname_src_mask);
7343         if (!NT_STATUS_IS_OK(status)) {
7344                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7345                 goto out;
7346         }
7347
7348         /*
7349          * We should only check the mangled cache
7350          * here if unix_convert failed. This means
7351          * that the path in 'mask' doesn't exist
7352          * on the file system and so we need to look
7353          * for a possible mangle. This patch from
7354          * Tine Smukavec <valentin.smukavec@hermes.si>.
7355          */
7356         if (!VALID_STAT(smb_fname_src->st) &&
7357             mangle_is_mangled(fname_src_mask, conn->params)) {
7358                 char *new_mask = NULL;
7359                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7360                                             &new_mask, conn->params);
7361
7362                 /* Use demangled name if one was successfully found. */
7363                 if (new_mask) {
7364                         TALLOC_FREE(fname_src_mask);
7365                         fname_src_mask = new_mask;
7366                 }
7367         }
7368
7369         if (!source_has_wild) {
7370
7371                 /*
7372                  * Only one file needs to be copied. Append the mask back onto
7373                  * the directory.
7374                  */
7375                 TALLOC_FREE(smb_fname_src->base_name);
7376                 if (ISDOT(fname_src_dir)) {
7377                         /* Ensure we use canonical names on open. */
7378                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7379                                                         "%s",
7380                                                         fname_src_mask);
7381                 } else {
7382                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7383                                                         "%s/%s",
7384                                                         fname_src_dir,
7385                                                         fname_src_mask);
7386                 }
7387                 if (!smb_fname_src->base_name) {
7388                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7389                         goto out;
7390                 }
7391
7392                 if (dest_has_wild) {
7393                         char *fname_dst_mod = NULL;
7394                         if (!resolve_wildcards(smb_fname_dst,
7395                                                smb_fname_src->base_name,
7396                                                smb_fname_dst->base_name,
7397                                                &fname_dst_mod)) {
7398                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7399                                 goto out;
7400                         }
7401                         TALLOC_FREE(smb_fname_dst->base_name);
7402                         smb_fname_dst->base_name = fname_dst_mod;
7403                 }
7404
7405                 status = check_name(conn, smb_fname_src->base_name);
7406                 if (!NT_STATUS_IS_OK(status)) {
7407                         reply_nterror(req, status);
7408                         goto out;
7409                 }
7410
7411                 status = check_name(conn, smb_fname_dst->base_name);
7412                 if (!NT_STATUS_IS_OK(status)) {
7413                         reply_nterror(req, status);
7414                         goto out;
7415                 }
7416
7417                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7418                                    ofun, count, target_is_directory);
7419
7420                 if(!NT_STATUS_IS_OK(status)) {
7421                         reply_nterror(req, status);
7422                         goto out;
7423                 } else {
7424                         count++;
7425                 }
7426         } else {
7427                 struct smb_Dir *dir_hnd = NULL;
7428                 const char *dname = NULL;
7429                 char *talloced = NULL;
7430                 long offset = 0;
7431
7432                 /*
7433                  * There is a wildcard that requires us to actually read the
7434                  * src dir and copy each file matching the mask to the dst.
7435                  * Right now streams won't be copied, but this could
7436                  * presumably be added with a nested loop for reach dir entry.
7437                  */
7438                 SMB_ASSERT(!smb_fname_src->stream_name);
7439                 SMB_ASSERT(!smb_fname_dst->stream_name);
7440
7441                 smb_fname_src->stream_name = NULL;
7442                 smb_fname_dst->stream_name = NULL;
7443
7444                 if (strequal(fname_src_mask,"????????.???")) {
7445                         TALLOC_FREE(fname_src_mask);
7446                         fname_src_mask = talloc_strdup(ctx, "*");
7447                         if (!fname_src_mask) {
7448                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7449                                 goto out;
7450                         }
7451                 }
7452
7453                 status = check_name(conn, fname_src_dir);
7454                 if (!NT_STATUS_IS_OK(status)) {
7455                         reply_nterror(req, status);
7456                         goto out;
7457                 }
7458
7459                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7460                 if (dir_hnd == NULL) {
7461                         status = map_nt_error_from_unix(errno);
7462                         reply_nterror(req, status);
7463                         goto out;
7464                 }
7465
7466                 error = ERRbadfile;
7467
7468                 /* Iterate over the src dir copying each entry to the dst. */
7469                 while ((dname = ReadDirName(dir_hnd, &offset,
7470                                             &smb_fname_src->st, &talloced))) {
7471                         char *destname = NULL;
7472
7473                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7474                                 TALLOC_FREE(talloced);
7475                                 continue;
7476                         }
7477
7478                         if (!is_visible_file(conn, fname_src_dir, dname,
7479                                              &smb_fname_src->st, false)) {
7480                                 TALLOC_FREE(talloced);
7481                                 continue;
7482                         }
7483
7484                         if(!mask_match(dname, fname_src_mask,
7485                                        conn->case_sensitive)) {
7486                                 TALLOC_FREE(talloced);
7487                                 continue;
7488                         }
7489
7490                         error = ERRnoaccess;
7491
7492                         /* Get the src smb_fname struct setup. */
7493                         TALLOC_FREE(smb_fname_src->base_name);
7494                         if (ISDOT(fname_src_dir)) {
7495                                 /* Ensure we use canonical names on open. */
7496                                 smb_fname_src->base_name =
7497                                         talloc_asprintf(smb_fname_src, "%s",
7498                                                 dname);
7499                         } else {
7500                                 smb_fname_src->base_name =
7501                                         talloc_asprintf(smb_fname_src, "%s/%s",
7502                                                 fname_src_dir, dname);
7503                         }
7504
7505                         if (!smb_fname_src->base_name) {
7506                                 TALLOC_FREE(dir_hnd);
7507                                 TALLOC_FREE(talloced);
7508                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7509                                 goto out;
7510                         }
7511
7512                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7513                                                smb_fname_dst->base_name,
7514                                                &destname)) {
7515                                 TALLOC_FREE(talloced);
7516                                 continue;
7517                         }
7518                         if (!destname) {
7519                                 TALLOC_FREE(dir_hnd);
7520                                 TALLOC_FREE(talloced);
7521                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7522                                 goto out;
7523                         }
7524
7525                         TALLOC_FREE(smb_fname_dst->base_name);
7526                         smb_fname_dst->base_name = destname;
7527
7528                         status = check_name(conn, smb_fname_src->base_name);
7529                         if (!NT_STATUS_IS_OK(status)) {
7530                                 TALLOC_FREE(dir_hnd);
7531                                 TALLOC_FREE(talloced);
7532                                 reply_nterror(req, status);
7533                                 goto out;
7534                         }
7535
7536                         status = check_name(conn, smb_fname_dst->base_name);
7537                         if (!NT_STATUS_IS_OK(status)) {
7538                                 TALLOC_FREE(dir_hnd);
7539                                 TALLOC_FREE(talloced);
7540                                 reply_nterror(req, status);
7541                                 goto out;
7542                         }
7543
7544                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7545                                 smb_fname_src->base_name,
7546                                 smb_fname_dst->base_name));
7547
7548                         status = copy_file(ctx, conn, smb_fname_src,
7549                                            smb_fname_dst, ofun, count,
7550                                            target_is_directory);
7551                         if (NT_STATUS_IS_OK(status)) {
7552                                 count++;
7553                         }
7554
7555                         TALLOC_FREE(talloced);
7556                 }
7557                 TALLOC_FREE(dir_hnd);
7558         }
7559
7560         if (count == 0) {
7561                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7562                 goto out;
7563         }
7564
7565         reply_outbuf(req, 1, 0);
7566         SSVAL(req->outbuf,smb_vwv0,count);
7567  out:
7568         TALLOC_FREE(smb_fname_src);
7569         TALLOC_FREE(smb_fname_dst);
7570         TALLOC_FREE(fname_src);
7571         TALLOC_FREE(fname_dst);
7572         TALLOC_FREE(fname_src_mask);
7573         TALLOC_FREE(fname_src_dir);
7574
7575         END_PROFILE(SMBcopy);
7576         return;
7577 }
7578
7579 #undef DBGC_CLASS
7580 #define DBGC_CLASS DBGC_LOCKING
7581
7582 /****************************************************************************
7583  Get a lock pid, dealing with large count requests.
7584 ****************************************************************************/
7585
7586 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7587                     bool large_file_format)
7588 {
7589         if(!large_file_format)
7590                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7591         else
7592                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7593 }
7594
7595 /****************************************************************************
7596  Get a lock count, dealing with large count requests.
7597 ****************************************************************************/
7598
7599 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7600                         bool large_file_format)
7601 {
7602         uint64_t count = 0;
7603
7604         if(!large_file_format) {
7605                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7606         } else {
7607                 /*
7608                  * No BVAL, this is reversed!
7609                  */
7610                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7611                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7612         }
7613
7614         return count;
7615 }
7616
7617 /****************************************************************************
7618  Get a lock offset, dealing with large offset requests.
7619 ****************************************************************************/
7620
7621 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7622                          bool large_file_format)
7623 {
7624         uint64_t offset = 0;
7625
7626         if(!large_file_format) {
7627                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7628         } else {
7629                 /*
7630                  * No BVAL, this is reversed!
7631                  */
7632                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7633                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7634         }
7635
7636         return offset;
7637 }
7638
7639 NTSTATUS smbd_do_locking(struct smb_request *req,
7640                          files_struct *fsp,
7641                          uint8_t type,
7642                          int32_t timeout,
7643                          uint16_t num_locks,
7644                          struct smbd_lock_element *locks,
7645                          bool *async)
7646 {
7647         connection_struct *conn = req->conn;
7648         int i;
7649         NTSTATUS status = NT_STATUS_OK;
7650
7651         *async = false;
7652
7653         /* Setup the timeout in seconds. */
7654
7655         if (!lp_blocking_locks(SNUM(conn))) {
7656                 timeout = 0;
7657         }
7658
7659         for(i = 0; i < (int)num_locks; i++) {
7660                 struct smbd_lock_element *e = &locks[i];
7661
7662                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7663                           "%llu, file %s timeout = %d\n",
7664                           (double)e->offset,
7665                           (double)e->count,
7666                           (unsigned long long)e->smblctx,
7667                           fsp_str_dbg(fsp),
7668                           (int)timeout));
7669
7670                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7671                         struct blocking_lock_record *blr = NULL;
7672
7673                         if (num_locks > 1) {
7674                                 /*
7675                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7676                                  * if the lock vector contains one entry. When given multiple cancel
7677                                  * requests in a single PDU we expect the server to return an
7678                                  * error. Windows servers seem to accept the request but only
7679                                  * cancel the first lock.
7680                                  * JRA - Do what Windows does (tm) :-).
7681                                  */
7682
7683 #if 0
7684                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7685                                 return NT_STATUS_DOS(ERRDOS,
7686                                                 ERRcancelviolation);
7687 #else
7688                                 /* Windows behavior. */
7689                                 if (i != 0) {
7690                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7691                                                 "cancel request\n"));
7692                                         continue;
7693                                 }
7694 #endif
7695                         }
7696
7697                         if (lp_blocking_locks(SNUM(conn))) {
7698
7699                                 /* Schedule a message to ourselves to
7700                                    remove the blocking lock record and
7701                                    return the right error. */
7702
7703                                 blr = blocking_lock_cancel_smb1(fsp,
7704                                                 e->smblctx,
7705                                                 e->offset,
7706                                                 e->count,
7707                                                 WINDOWS_LOCK,
7708                                                 type,
7709                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7710                                 if (blr == NULL) {
7711                                         return NT_STATUS_DOS(
7712                                                         ERRDOS,
7713                                                         ERRcancelviolation);
7714                                 }
7715                         }
7716                         /* Remove a matching pending lock. */
7717                         status = do_lock_cancel(fsp,
7718                                                 e->smblctx,
7719                                                 e->count,
7720                                                 e->offset,
7721                                                 WINDOWS_LOCK);
7722                 } else {
7723                         bool blocking_lock = timeout ? true : false;
7724                         bool defer_lock = false;
7725                         struct byte_range_lock *br_lck;
7726                         uint64_t block_smblctx;
7727
7728                         br_lck = do_lock(req->sconn->msg_ctx,
7729                                         fsp,
7730                                         e->smblctx,
7731                                         e->count,
7732                                         e->offset, 
7733                                         e->brltype,
7734                                         WINDOWS_LOCK,
7735                                         blocking_lock,
7736                                         &status,
7737                                         &block_smblctx);
7738
7739                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7740                                 /* Windows internal resolution for blocking locks seems
7741                                    to be about 200ms... Don't wait for less than that. JRA. */
7742                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7743                                         timeout = lp_lock_spin_time();
7744                                 }
7745                                 defer_lock = true;
7746                         }
7747
7748                         /* If a lock sent with timeout of zero would fail, and
7749                          * this lock has been requested multiple times,
7750                          * according to brl_lock_failed() we convert this
7751                          * request to a blocking lock with a timeout of between
7752                          * 150 - 300 milliseconds.
7753                          *
7754                          * If lp_lock_spin_time() has been set to 0, we skip
7755                          * this blocking retry and fail immediately.
7756                          *
7757                          * Replacement for do_lock_spin(). JRA. */
7758
7759                         if (!req->sconn->using_smb2 &&
7760                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7761                             lp_lock_spin_time() && !blocking_lock &&
7762                             NT_STATUS_EQUAL((status),
7763                                 NT_STATUS_FILE_LOCK_CONFLICT))
7764                         {
7765                                 defer_lock = true;
7766                                 timeout = lp_lock_spin_time();
7767                         }
7768
7769                         if (br_lck && defer_lock) {
7770                                 /*
7771                                  * A blocking lock was requested. Package up
7772                                  * this smb into a queued request and push it
7773                                  * onto the blocking lock queue.
7774                                  */
7775                                 if(push_blocking_lock_request(br_lck,
7776                                                         req,
7777                                                         fsp,
7778                                                         timeout,
7779                                                         i,
7780                                                         e->smblctx,
7781                                                         e->brltype,
7782                                                         WINDOWS_LOCK,
7783                                                         e->offset,
7784                                                         e->count,
7785                                                         block_smblctx)) {
7786                                         TALLOC_FREE(br_lck);
7787                                         *async = true;
7788                                         return NT_STATUS_OK;
7789                                 }
7790                         }
7791
7792                         TALLOC_FREE(br_lck);
7793                 }
7794
7795                 if (!NT_STATUS_IS_OK(status)) {
7796                         break;
7797                 }
7798         }
7799
7800         /* If any of the above locks failed, then we must unlock
7801            all of the previous locks (X/Open spec). */
7802
7803         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7804
7805                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7806                         i = -1; /* we want to skip the for loop */
7807                 }
7808
7809                 /*
7810                  * Ensure we don't do a remove on the lock that just failed,
7811                  * as under POSIX rules, if we have a lock already there, we
7812                  * will delete it (and we shouldn't) .....
7813                  */
7814                 for(i--; i >= 0; i--) {
7815                         struct smbd_lock_element *e = &locks[i];
7816
7817                         do_unlock(req->sconn->msg_ctx,
7818                                 fsp,
7819                                 e->smblctx,
7820                                 e->count,
7821                                 e->offset,
7822                                 WINDOWS_LOCK);
7823                 }
7824                 return status;
7825         }
7826
7827         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7828                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7829
7830         return NT_STATUS_OK;
7831 }
7832
7833 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7834                            files_struct *fsp,
7835                            uint16_t num_ulocks,
7836                            struct smbd_lock_element *ulocks)
7837 {
7838         int i;
7839
7840         for(i = 0; i < (int)num_ulocks; i++) {
7841                 struct smbd_lock_element *e = &ulocks[i];
7842                 NTSTATUS status;
7843
7844                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7845                           "pid %u, file %s\n", __func__,
7846                           (double)e->offset,
7847                           (double)e->count,
7848                           (unsigned int)e->smblctx,
7849                           fsp_str_dbg(fsp)));
7850
7851                 if (e->brltype != UNLOCK_LOCK) {
7852                         /* this can only happen with SMB2 */
7853                         return NT_STATUS_INVALID_PARAMETER;
7854                 }
7855
7856                 status = do_unlock(req->sconn->msg_ctx,
7857                                 fsp,
7858                                 e->smblctx,
7859                                 e->count,
7860                                 e->offset,
7861                                 WINDOWS_LOCK);
7862
7863                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7864                            nt_errstr(status)));
7865
7866                 if (!NT_STATUS_IS_OK(status)) {
7867                         return status;
7868                 }
7869         }
7870
7871         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7872                   num_ulocks));
7873
7874         return NT_STATUS_OK;
7875 }
7876
7877 /****************************************************************************
7878  Reply to a lockingX request.
7879 ****************************************************************************/
7880
7881 void reply_lockingX(struct smb_request *req)
7882 {
7883         connection_struct *conn = req->conn;
7884         files_struct *fsp;
7885         unsigned char locktype;
7886         unsigned char oplocklevel;
7887         uint16 num_ulocks;
7888         uint16 num_locks;
7889         int32 lock_timeout;
7890         int i;
7891         const uint8_t *data;
7892         bool large_file_format;
7893         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7894         struct smbd_lock_element *ulocks;
7895         struct smbd_lock_element *locks;
7896         bool async = false;
7897
7898         START_PROFILE(SMBlockingX);
7899
7900         if (req->wct < 8) {
7901                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7902                 END_PROFILE(SMBlockingX);
7903                 return;
7904         }
7905
7906         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7907         locktype = CVAL(req->vwv+3, 0);
7908         oplocklevel = CVAL(req->vwv+3, 1);
7909         num_ulocks = SVAL(req->vwv+6, 0);
7910         num_locks = SVAL(req->vwv+7, 0);
7911         lock_timeout = IVAL(req->vwv+4, 0);
7912         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7913
7914         if (!check_fsp(conn, req, fsp)) {
7915                 END_PROFILE(SMBlockingX);
7916                 return;
7917         }
7918
7919         data = req->buf;
7920
7921         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7922                 /* we don't support these - and CANCEL_LOCK makes w2k
7923                    and XP reboot so I don't really want to be
7924                    compatible! (tridge) */
7925                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7926                 END_PROFILE(SMBlockingX);
7927                 return;
7928         }
7929
7930         /* Check if this is an oplock break on a file
7931            we have granted an oplock on.
7932         */
7933         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7934                 /* Client can insist on breaking to none. */
7935                 bool break_to_none = (oplocklevel == 0);
7936                 bool result;
7937
7938                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7939                          "for %s\n", (unsigned int)oplocklevel,
7940                          fsp_fnum_dbg(fsp)));
7941
7942                 /*
7943                  * Make sure we have granted an exclusive or batch oplock on
7944                  * this file.
7945                  */
7946
7947                 if (fsp->oplock_type == 0) {
7948
7949                         /* The Samba4 nbench simulator doesn't understand
7950                            the difference between break to level2 and break
7951                            to none from level2 - it sends oplock break
7952                            replies in both cases. Don't keep logging an error
7953                            message here - just ignore it. JRA. */
7954
7955                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7956                                  "client for %s (oplock=%d) and no "
7957                                  "oplock granted on this file (%s).\n",
7958                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
7959                                  fsp_str_dbg(fsp)));
7960
7961                         /* if this is a pure oplock break request then don't
7962                          * send a reply */
7963                         if (num_locks == 0 && num_ulocks == 0) {
7964                                 END_PROFILE(SMBlockingX);
7965                                 return;
7966                         } else {
7967                                 END_PROFILE(SMBlockingX);
7968                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7969                                 return;
7970                         }
7971                 }
7972
7973                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7974                     (break_to_none)) {
7975                         result = remove_oplock(fsp);
7976                 } else {
7977                         result = downgrade_oplock(fsp);
7978                 }
7979
7980                 if (!result) {
7981                         DEBUG(0, ("reply_lockingX: error in removing "
7982                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7983                         /* Hmmm. Is this panic justified? */
7984                         smb_panic("internal tdb error");
7985                 }
7986
7987                 /* if this is a pure oplock break request then don't send a
7988                  * reply */
7989                 if (num_locks == 0 && num_ulocks == 0) {
7990                         /* Sanity check - ensure a pure oplock break is not a
7991                            chained request. */
7992                         if (CVAL(req->vwv+0, 0) != 0xff) {
7993                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7994                                          "break is a chained %d request !\n",
7995                                          (unsigned int)CVAL(req->vwv+0, 0)));
7996                         }
7997                         END_PROFILE(SMBlockingX);
7998                         return;
7999                 }
8000         }
8001
8002         if (req->buflen <
8003             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8004                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8005                 END_PROFILE(SMBlockingX);
8006                 return;
8007         }
8008
8009         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8010         if (ulocks == NULL) {
8011                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8012                 END_PROFILE(SMBlockingX);
8013                 return;
8014         }
8015
8016         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8017         if (locks == NULL) {
8018                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8019                 END_PROFILE(SMBlockingX);
8020                 return;
8021         }
8022
8023         /* Data now points at the beginning of the list
8024            of smb_unlkrng structs */
8025         for(i = 0; i < (int)num_ulocks; i++) {
8026                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8027                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8028                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8029                 ulocks[i].brltype = UNLOCK_LOCK;
8030         }
8031
8032         /* Now do any requested locks */
8033         data += ((large_file_format ? 20 : 10)*num_ulocks);
8034
8035         /* Data now points at the beginning of the list
8036            of smb_lkrng structs */
8037
8038         for(i = 0; i < (int)num_locks; i++) {
8039                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8040                 locks[i].count = get_lock_count(data, i, large_file_format);
8041                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8042
8043                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8044                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8045                                 locks[i].brltype = PENDING_READ_LOCK;
8046                         } else {
8047                                 locks[i].brltype = READ_LOCK;
8048                         }
8049                 } else {
8050                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8051                                 locks[i].brltype = PENDING_WRITE_LOCK;
8052                         } else {
8053                                 locks[i].brltype = WRITE_LOCK;
8054                         }
8055                 }
8056         }
8057
8058         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8059         if (!NT_STATUS_IS_OK(status)) {
8060                 END_PROFILE(SMBlockingX);
8061                 reply_nterror(req, status);
8062                 return;
8063         }
8064
8065         status = smbd_do_locking(req, fsp,
8066                                  locktype, lock_timeout,
8067                                  num_locks, locks,
8068                                  &async);
8069         if (!NT_STATUS_IS_OK(status)) {
8070                 END_PROFILE(SMBlockingX);
8071                 reply_nterror(req, status);
8072                 return;
8073         }
8074         if (async) {
8075                 END_PROFILE(SMBlockingX);
8076                 return;
8077         }
8078
8079         reply_outbuf(req, 2, 0);
8080         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8081         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8082
8083         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8084                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8085
8086         END_PROFILE(SMBlockingX);
8087 }
8088
8089 #undef DBGC_CLASS
8090 #define DBGC_CLASS DBGC_ALL
8091
8092 /****************************************************************************
8093  Reply to a SMBreadbmpx (read block multiplex) request.
8094  Always reply with an error, if someone has a platform really needs this,
8095  please contact vl@samba.org
8096 ****************************************************************************/
8097
8098 void reply_readbmpx(struct smb_request *req)
8099 {
8100         START_PROFILE(SMBreadBmpx);
8101         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8102         END_PROFILE(SMBreadBmpx);
8103         return;
8104 }
8105
8106 /****************************************************************************
8107  Reply to a SMBreadbs (read block multiplex secondary) request.
8108  Always reply with an error, if someone has a platform really needs this,
8109  please contact vl@samba.org
8110 ****************************************************************************/
8111
8112 void reply_readbs(struct smb_request *req)
8113 {
8114         START_PROFILE(SMBreadBs);
8115         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8116         END_PROFILE(SMBreadBs);
8117         return;
8118 }
8119
8120 /****************************************************************************
8121  Reply to a SMBsetattrE.
8122 ****************************************************************************/
8123
8124 void reply_setattrE(struct smb_request *req)
8125 {
8126         connection_struct *conn = req->conn;
8127         struct smb_file_time ft;
8128         files_struct *fsp;
8129         NTSTATUS status;
8130
8131         START_PROFILE(SMBsetattrE);
8132         ZERO_STRUCT(ft);
8133
8134         if (req->wct < 7) {
8135                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8136                 goto out;
8137         }
8138
8139         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8140
8141         if(!fsp || (fsp->conn != conn)) {
8142                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8143                 goto out;
8144         }
8145
8146         /*
8147          * Convert the DOS times into unix times.
8148          */
8149
8150         ft.atime = convert_time_t_to_timespec(
8151             srv_make_unix_date2(req->vwv+3));
8152         ft.mtime = convert_time_t_to_timespec(
8153             srv_make_unix_date2(req->vwv+5));
8154         ft.create_time = convert_time_t_to_timespec(
8155             srv_make_unix_date2(req->vwv+1));
8156
8157         reply_outbuf(req, 0, 0);
8158
8159         /* 
8160          * Patch from Ray Frush <frush@engr.colostate.edu>
8161          * Sometimes times are sent as zero - ignore them.
8162          */
8163
8164         /* Ensure we have a valid stat struct for the source. */
8165         status = vfs_stat_fsp(fsp);
8166         if (!NT_STATUS_IS_OK(status)) {
8167                 reply_nterror(req, status);
8168                 goto out;
8169         }
8170
8171         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8172                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8173                 goto out;
8174         }
8175
8176         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8177         if (!NT_STATUS_IS_OK(status)) {
8178                 reply_nterror(req, status);
8179                 goto out;
8180         }
8181
8182         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8183                " createtime=%u\n",
8184                 fsp_fnum_dbg(fsp),
8185                 (unsigned int)ft.atime.tv_sec,
8186                 (unsigned int)ft.mtime.tv_sec,
8187                 (unsigned int)ft.create_time.tv_sec
8188                 ));
8189  out:
8190         END_PROFILE(SMBsetattrE);
8191         return;
8192 }
8193
8194
8195 /* Back from the dead for OS/2..... JRA. */
8196
8197 /****************************************************************************
8198  Reply to a SMBwritebmpx (write block multiplex primary) request.
8199  Always reply with an error, if someone has a platform really needs this,
8200  please contact vl@samba.org
8201 ****************************************************************************/
8202
8203 void reply_writebmpx(struct smb_request *req)
8204 {
8205         START_PROFILE(SMBwriteBmpx);
8206         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8207         END_PROFILE(SMBwriteBmpx);
8208         return;
8209 }
8210
8211 /****************************************************************************
8212  Reply to a SMBwritebs (write block multiplex secondary) request.
8213  Always reply with an error, if someone has a platform really needs this,
8214  please contact vl@samba.org
8215 ****************************************************************************/
8216
8217 void reply_writebs(struct smb_request *req)
8218 {
8219         START_PROFILE(SMBwriteBs);
8220         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8221         END_PROFILE(SMBwriteBs);
8222         return;
8223 }
8224
8225 /****************************************************************************
8226  Reply to a SMBgetattrE.
8227 ****************************************************************************/
8228
8229 void reply_getattrE(struct smb_request *req)
8230 {
8231         connection_struct *conn = req->conn;
8232         int mode;
8233         files_struct *fsp;
8234         struct timespec create_ts;
8235
8236         START_PROFILE(SMBgetattrE);
8237
8238         if (req->wct < 1) {
8239                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8240                 END_PROFILE(SMBgetattrE);
8241                 return;
8242         }
8243
8244         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8245
8246         if(!fsp || (fsp->conn != conn)) {
8247                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8248                 END_PROFILE(SMBgetattrE);
8249                 return;
8250         }
8251
8252         /* Do an fstat on this file */
8253         if(fsp_stat(fsp)) {
8254                 reply_nterror(req, map_nt_error_from_unix(errno));
8255                 END_PROFILE(SMBgetattrE);
8256                 return;
8257         }
8258
8259         mode = dos_mode(conn, fsp->fsp_name);
8260
8261         /*
8262          * Convert the times into dos times. Set create
8263          * date to be last modify date as UNIX doesn't save
8264          * this.
8265          */
8266
8267         reply_outbuf(req, 11, 0);
8268
8269         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8270         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8271         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8272                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8273         /* Should we check pending modtime here ? JRA */
8274         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8275                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8276
8277         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8278                 SIVAL(req->outbuf, smb_vwv6, 0);
8279                 SIVAL(req->outbuf, smb_vwv8, 0);
8280         } else {
8281                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8282                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8283                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8284         }
8285         SSVAL(req->outbuf,smb_vwv10, mode);
8286
8287         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8288
8289         END_PROFILE(SMBgetattrE);
8290         return;
8291 }