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