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