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