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