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