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