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