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