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