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