dfb279db61bf2e403e383d82a6a71fdc3b27b0bc
[kai/samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45
46 /****************************************************************************
47  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
48  path or anything including wildcards.
49  We're assuming here that '/' is not the second byte in any multibyte char
50  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
51  set.
52 ****************************************************************************/
53
54 /* Custom version for processing POSIX paths. */
55 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56
57 static NTSTATUS check_path_syntax_internal(char *path,
58                                            bool posix_path,
59                                            bool *p_last_component_contains_wcard)
60 {
61         char *d = path;
62         const char *s = path;
63         NTSTATUS ret = NT_STATUS_OK;
64         bool start_of_name_component = True;
65         bool stream_started = false;
66
67         *p_last_component_contains_wcard = False;
68
69         while (*s) {
70                 if (stream_started) {
71                         switch (*s) {
72                         case '/':
73                         case '\\':
74                                 return NT_STATUS_OBJECT_NAME_INVALID;
75                         case ':':
76                                 if (s[1] == '\0') {
77                                         return NT_STATUS_OBJECT_NAME_INVALID;
78                                 }
79                                 if (strchr_m(&s[1], ':')) {
80                                         return NT_STATUS_OBJECT_NAME_INVALID;
81                                 }
82                                 break;
83                         }
84                 }
85
86                 if ((*s == ':') && !posix_path && !stream_started) {
87                         if (*p_last_component_contains_wcard) {
88                                 return NT_STATUS_OBJECT_NAME_INVALID;
89                         }
90                         /* Stream names allow more characters than file names.
91                            We're overloading posix_path here to allow a wider
92                            range of characters. If stream_started is true this
93                            is still a Windows path even if posix_path is true.
94                            JRA.
95                         */
96                         stream_started = true;
97                         start_of_name_component = false;
98                         posix_path = true;
99
100                         if (s[1] == '\0') {
101                                 return NT_STATUS_OBJECT_NAME_INVALID;
102                         }
103                 }
104
105                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106                         /*
107                          * Safe to assume is not the second part of a mb char
108                          * as this is handled below.
109                          */
110                         /* Eat multiple '/' or '\\' */
111                         while (IS_PATH_SEP(*s,posix_path)) {
112                                 s++;
113                         }
114                         if ((d != path) && (*s != '\0')) {
115                                 /* We only care about non-leading or trailing '/' or '\\' */
116                                 *d++ = '/';
117                         }
118
119                         start_of_name_component = True;
120                         /* New component. */
121                         *p_last_component_contains_wcard = False;
122                         continue;
123                 }
124
125                 if (start_of_name_component) {
126                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
127                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
128
129                                 /*
130                                  * No mb char starts with '.' so we're safe checking the directory separator here.
131                                  */
132
133                                 /* If  we just added a '/' - delete it */
134                                 if ((d > path) && (*(d-1) == '/')) {
135                                         *(d-1) = '\0';
136                                         d--;
137                                 }
138
139                                 /* Are we at the start ? Can't go back further if so. */
140                                 if (d <= path) {
141                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
142                                         break;
143                                 }
144                                 /* Go back one level... */
145                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
146                                 /* NOTE - if this assumption is invalid we are not in good shape... */
147                                 /* Decrement d first as d points to the *next* char to write into. */
148                                 for (d--; d > path; d--) {
149                                         if (*d == '/')
150                                                 break;
151                                 }
152                                 s += 2; /* Else go past the .. */
153                                 /* We're still at the start of a name component, just the previous one. */
154                                 continue;
155
156                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157                                 if (posix_path) {
158                                         /* Eat the '.' */
159                                         s++;
160                                         continue;
161                                 }
162                         }
163
164                 }
165
166                 if (!(*s & 0x80)) {
167                         if (!posix_path) {
168                                 if (*s <= 0x1f || *s == '|') {
169                                         return NT_STATUS_OBJECT_NAME_INVALID;
170                                 }
171                                 switch (*s) {
172                                         case '*':
173                                         case '?':
174                                         case '<':
175                                         case '>':
176                                         case '"':
177                                                 *p_last_component_contains_wcard = True;
178                                                 break;
179                                         default:
180                                                 break;
181                                 }
182                         }
183                         *d++ = *s++;
184                 } else {
185                         size_t siz;
186                         /* Get the size of the next MB character. */
187                         next_codepoint(s,&siz);
188                         switch(siz) {
189                                 case 5:
190                                         *d++ = *s++;
191                                         /*fall through*/
192                                 case 4:
193                                         *d++ = *s++;
194                                         /*fall through*/
195                                 case 3:
196                                         *d++ = *s++;
197                                         /*fall through*/
198                                 case 2:
199                                         *d++ = *s++;
200                                         /*fall through*/
201                                 case 1:
202                                         *d++ = *s++;
203                                         break;
204                                 default:
205                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
206                                         *d = '\0';
207                                         return NT_STATUS_INVALID_PARAMETER;
208                         }
209                 }
210                 start_of_name_component = False;
211         }
212
213         *d = '\0';
214
215         return ret;
216 }
217
218 /****************************************************************************
219  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220  No wildcards allowed.
221 ****************************************************************************/
222
223 NTSTATUS check_path_syntax(char *path)
224 {
225         bool ignore;
226         return check_path_syntax_internal(path, False, &ignore);
227 }
228
229 /****************************************************************************
230  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
231  Wildcards allowed - p_contains_wcard returns true if the last component contained
232  a wildcard.
233 ****************************************************************************/
234
235 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 {
237         return check_path_syntax_internal(path, False, p_contains_wcard);
238 }
239
240 /****************************************************************************
241  Check the path for a POSIX client.
242  We're assuming here that '/' is not the second byte in any multibyte char
243  set (a safe assumption).
244 ****************************************************************************/
245
246 NTSTATUS check_path_syntax_posix(char *path)
247 {
248         bool ignore;
249         return check_path_syntax_internal(path, True, &ignore);
250 }
251
252 /****************************************************************************
253  Pull a string and check the path allowing a wilcard - provide for error return.
254 ****************************************************************************/
255
256 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
257                         const char *base_ptr,
258                         uint16 smb_flags2,
259                         char **pp_dest,
260                         const char *src,
261                         size_t src_len,
262                         int flags,
263                         NTSTATUS *err,
264                         bool *contains_wcard)
265 {
266         size_t ret;
267
268         *pp_dest = NULL;
269
270         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
271                                  src_len, flags);
272
273         if (!*pp_dest) {
274                 *err = NT_STATUS_INVALID_PARAMETER;
275                 return ret;
276         }
277
278         *contains_wcard = False;
279
280         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281                 /*
282                  * For a DFS path the function parse_dfs_path()
283                  * will do the path processing, just make a copy.
284                  */
285                 *err = NT_STATUS_OK;
286                 return ret;
287         }
288
289         if (lp_posix_pathnames()) {
290                 *err = check_path_syntax_posix(*pp_dest);
291         } else {
292                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
293         }
294
295         return ret;
296 }
297
298 /****************************************************************************
299  Pull a string and check the path - provide for error return.
300 ****************************************************************************/
301
302 size_t srvstr_get_path(TALLOC_CTX *ctx,
303                         const char *base_ptr,
304                         uint16 smb_flags2,
305                         char **pp_dest,
306                         const char *src,
307                         size_t src_len,
308                         int flags,
309                         NTSTATUS *err)
310 {
311         bool ignore;
312         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
313                                      src_len, flags, err, &ignore);
314 }
315
316 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
317                                  char **pp_dest, const char *src, int flags,
318                                  NTSTATUS *err, bool *contains_wcard)
319 {
320         return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
321                                      pp_dest, src, smbreq_bufrem(req, src),
322                                      flags, err, contains_wcard);
323 }
324
325 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
326                            char **pp_dest, const char *src, int flags,
327                            NTSTATUS *err)
328 {
329         bool ignore;
330         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
331                                          flags, err, &ignore);
332 }
333
334 /****************************************************************************
335  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
336 ****************************************************************************/
337
338 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
339                     files_struct *fsp)
340 {
341         if ((fsp == NULL) || (conn == NULL)) {
342                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
343                 return False;
344         }
345         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
346                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
347                 return False;
348         }
349         return True;
350 }
351
352 /****************************************************************************
353  Check if we have a correct fsp pointing to a file.
354 ****************************************************************************/
355
356 bool check_fsp(connection_struct *conn, struct smb_request *req,
357                files_struct *fsp)
358 {
359         if (!check_fsp_open(conn, req, fsp)) {
360                 return False;
361         }
362         if (fsp->is_directory) {
363                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
364                 return False;
365         }
366         if (fsp->fh->fd == -1) {
367                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
368                 return False;
369         }
370         fsp->num_smb_operations++;
371         return True;
372 }
373
374 /****************************************************************************
375  Check if we have a correct fsp pointing to a quota fake file. Replacement for
376  the CHECK_NTQUOTA_HANDLE_OK macro.
377 ****************************************************************************/
378
379 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
380                               files_struct *fsp)
381 {
382         if (!check_fsp_open(conn, req, fsp)) {
383                 return false;
384         }
385
386         if (fsp->is_directory) {
387                 return false;
388         }
389
390         if (fsp->fake_file_handle == NULL) {
391                 return false;
392         }
393
394         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
395                 return false;
396         }
397
398         if (fsp->fake_file_handle->private_data == NULL) {
399                 return false;
400         }
401
402         return true;
403 }
404
405 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
406                                      const char *name, int name_type)
407 {
408         char *trim_name;
409         char *trim_name_type;
410         const char *retarget_parm;
411         char *retarget;
412         char *p;
413         int retarget_type = 0x20;
414         int retarget_port = NBT_SMB_PORT;
415         struct sockaddr_storage retarget_addr;
416         struct sockaddr_in *in_addr;
417         bool ret = false;
418         uint8_t outbuf[10];
419
420         if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
421                 return false;
422         }
423
424         trim_name = talloc_strdup(talloc_tos(), name);
425         if (trim_name == NULL) {
426                 goto fail;
427         }
428         trim_char(trim_name, ' ', ' ');
429
430         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
431                                          name_type);
432         if (trim_name_type == NULL) {
433                 goto fail;
434         }
435
436         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
437                                              trim_name_type, NULL);
438         if (retarget_parm == NULL) {
439                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
440                                                      trim_name, NULL);
441         }
442         if (retarget_parm == NULL) {
443                 goto fail;
444         }
445
446         retarget = talloc_strdup(trim_name, retarget_parm);
447         if (retarget == NULL) {
448                 goto fail;
449         }
450
451         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452
453         p = strchr(retarget, ':');
454         if (p != NULL) {
455                 *p++ = '\0';
456                 retarget_port = atoi(p);
457         }
458
459         p = strchr_m(retarget, '#');
460         if (p != NULL) {
461                 *p++ = '\0';
462                 if (sscanf(p, "%x", &retarget_type) != 1) {
463                         goto fail;
464                 }
465         }
466
467         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
468         if (!ret) {
469                 DEBUG(10, ("could not resolve %s\n", retarget));
470                 goto fail;
471         }
472
473         if (retarget_addr.ss_family != AF_INET) {
474                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
475                 goto fail;
476         }
477
478         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479
480         _smb_setlen(outbuf, 6);
481         SCVAL(outbuf, 0, 0x84);
482         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
483         *(uint16_t *)(outbuf+8) = htons(retarget_port);
484
485         if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
486                           NULL)) {
487                 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
488                                     "failed.");
489         }
490
491         ret = true;
492  fail:
493         TALLOC_FREE(trim_name);
494         return ret;
495 }
496
497 static void reply_called_name_not_present(char *outbuf)
498 {
499         smb_setlen(outbuf, 1);
500         SCVAL(outbuf, 0, 0x83);
501         SCVAL(outbuf, 4, 0x82);
502 }
503
504 /****************************************************************************
505  Reply to a (netbios-level) special message. 
506 ****************************************************************************/
507
508 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 {
510         int msg_type = CVAL(inbuf,0);
511         int msg_flags = CVAL(inbuf,1);
512         /*
513          * We only really use 4 bytes of the outbuf, but for the smb_setlen
514          * calculation & friends (srv_send_smb uses that) we need the full smb
515          * header.
516          */
517         char outbuf[smb_size];
518
519         memset(outbuf, '\0', sizeof(outbuf));
520
521         smb_setlen(outbuf,0);
522
523         switch (msg_type) {
524         case NBSSrequest: /* session request */
525         {
526                 /* inbuf_size is guarenteed to be at least 4. */
527                 fstring name1,name2;
528                 int name_type1, name_type2;
529                 int name_len1, name_len2;
530
531                 *name1 = *name2 = 0;
532
533                 if (sconn->nbt.got_session) {
534                         exit_server_cleanly("multiple session request not permitted");
535                 }
536
537                 SCVAL(outbuf,0,NBSSpositive);
538                 SCVAL(outbuf,3,0);
539
540                 /* inbuf_size is guaranteed to be at least 4. */
541                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
542                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
543                         DEBUG(0,("Invalid name length in session request\n"));
544                         reply_called_name_not_present(outbuf);
545                         break;
546                 }
547                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
548                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
549                         DEBUG(0,("Invalid name length in session request\n"));
550                         reply_called_name_not_present(outbuf);
551                         break;
552                 }
553
554                 name_type1 = name_extract((unsigned char *)inbuf,
555                                 inbuf_size,(unsigned int)4,name1);
556                 name_type2 = name_extract((unsigned char *)inbuf,
557                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
558
559                 if (name_type1 == -1 || name_type2 == -1) {
560                         DEBUG(0,("Invalid name type in session request\n"));
561                         reply_called_name_not_present(outbuf);
562                         break;
563                 }
564
565                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
566                          name1, name_type1, name2, name_type2));
567
568                 if (netbios_session_retarget(sconn, name1, name_type1)) {
569                         exit_server_cleanly("retargeted client");
570                 }
571
572                 /*
573                  * Windows NT/2k uses "*SMBSERVER" and XP uses
574                  * "*SMBSERV" arrggg!!!
575                  */
576                 if (strequal(name1, "*SMBSERVER     ")
577                     || strequal(name1, "*SMBSERV       "))  {
578                         char *raddr;
579
580                         raddr = tsocket_address_inet_addr_string(sconn->remote_address,
581                                                                  talloc_tos());
582                         if (raddr == NULL) {
583                                 exit_server_cleanly("could not allocate raddr");
584                         }
585
586                         fstrcpy(name1, raddr);
587                 }
588
589                 set_local_machine_name(name1, True);
590                 set_remote_machine_name(name2, True);
591
592                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
593                          get_local_machine_name(), get_remote_machine_name(),
594                          name_type2));
595
596                 if (name_type2 == 'R') {
597                         /* We are being asked for a pathworks session --- 
598                            no thanks! */
599                         reply_called_name_not_present(outbuf);
600                         break;
601                 }
602
603                 reload_services(sconn, conn_snum_used, true);
604                 reopen_logs();
605
606                 sconn->nbt.got_session = true;
607                 break;
608         }
609
610         case 0x89: /* session keepalive request 
611                       (some old clients produce this?) */
612                 SCVAL(outbuf,0,NBSSkeepalive);
613                 SCVAL(outbuf,3,0);
614                 break;
615
616         case NBSSpositive: /* positive session response */
617         case NBSSnegative: /* negative session response */
618         case NBSSretarget: /* retarget session response */
619                 DEBUG(0,("Unexpected session response\n"));
620                 break;
621
622         case NBSSkeepalive: /* session keepalive */
623         default:
624                 return;
625         }
626
627         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
628                     msg_type, msg_flags));
629
630         srv_send_smb(sconn, outbuf, false, 0, false, NULL);
631
632         if (CVAL(outbuf, 0) != 0x82) {
633                 exit_server_cleanly("invalid netbios session");
634         }
635         return;
636 }
637
638 /****************************************************************************
639  Reply to a tcon.
640  conn POINTER CAN BE NULL HERE !
641 ****************************************************************************/
642
643 void reply_tcon(struct smb_request *req)
644 {
645         connection_struct *conn = req->conn;
646         const char *service;
647         char *service_buf = NULL;
648         char *password = NULL;
649         char *dev = NULL;
650         int pwlen=0;
651         NTSTATUS nt_status;
652         const char *p;
653         TALLOC_CTX *ctx = talloc_tos();
654         struct smbd_server_connection *sconn = req->sconn;
655
656         START_PROFILE(SMBtcon);
657
658         if (req->buflen < 4) {
659                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
660                 END_PROFILE(SMBtcon);
661                 return;
662         }
663
664         p = (const char *)req->buf + 1;
665         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
666         p += 1;
667         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
668         p += pwlen+1;
669         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
670         p += 1;
671
672         if (service_buf == NULL || password == NULL || dev == NULL) {
673                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
674                 END_PROFILE(SMBtcon);
675                 return;
676         }
677         p = strrchr_m(service_buf,'\\');
678         if (p) {
679                 service = p+1;
680         } else {
681                 service = service_buf;
682         }
683
684         conn = make_connection(sconn,service,dev,
685                                req->vuid,&nt_status);
686         req->conn = conn;
687
688         if (!conn) {
689                 reply_nterror(req, nt_status);
690                 END_PROFILE(SMBtcon);
691                 return;
692         }
693
694         reply_outbuf(req, 2, 0);
695         SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
696         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
697         SSVAL(req->outbuf,smb_tid,conn->cnum);
698
699         DEBUG(3,("tcon service=%s cnum=%d\n",
700                  service, conn->cnum));
701
702         END_PROFILE(SMBtcon);
703         return;
704 }
705
706 /****************************************************************************
707  Reply to a tcon and X.
708  conn POINTER CAN BE NULL HERE !
709 ****************************************************************************/
710
711 void reply_tcon_and_X(struct smb_request *req)
712 {
713         connection_struct *conn = req->conn;
714         const char *service = NULL;
715         TALLOC_CTX *ctx = talloc_tos();
716         /* what the cleint thinks the device is */
717         char *client_devicetype = NULL;
718         /* what the server tells the client the share represents */
719         const char *server_devicetype;
720         NTSTATUS nt_status;
721         int passlen;
722         char *path = NULL;
723         const char *p, *q;
724         uint16 tcon_flags;
725         struct smbd_server_connection *sconn = req->sconn;
726
727         START_PROFILE(SMBtconX);
728
729         if (req->wct < 4) {
730                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
731                 END_PROFILE(SMBtconX);
732                 return;
733         }
734
735         passlen = SVAL(req->vwv+3, 0);
736         tcon_flags = SVAL(req->vwv+2, 0);
737
738         /* we might have to close an old one */
739         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
740                 struct smbXsrv_tcon *tcon;
741                 NTSTATUS status;
742
743                 tcon = conn->tcon;
744                 req->conn = NULL;
745                 conn = NULL;
746
747                 /*
748                  * TODO: cancel all outstanding requests on the tcon
749                  */
750                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
751                 if (!NT_STATUS_IS_OK(status)) {
752                         DEBUG(0, ("reply_tcon_and_X: "
753                                   "smbXsrv_tcon_disconnect() failed: %s\n",
754                                   nt_errstr(status)));
755                         /*
756                          * If we hit this case, there is something completely
757                          * wrong, so we better disconnect the transport connection.
758                          */
759                         END_PROFILE(SMBtconX);
760                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
761                         return;
762                 }
763
764                 TALLOC_FREE(tcon);
765         }
766
767         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
768                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
769                 END_PROFILE(SMBtconX);
770                 return;
771         }
772
773         if (sconn->smb1.negprot.encrypted_passwords) {
774                 p = (const char *)req->buf + passlen;
775         } else {
776                 p = (const char *)req->buf + passlen + 1;
777         }
778
779         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
780
781         if (path == NULL) {
782                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
783                 END_PROFILE(SMBtconX);
784                 return;
785         }
786
787         /*
788          * the service name can be either: \\server\share
789          * or share directly like on the DELL PowerVault 705
790          */
791         if (*path=='\\') {
792                 q = strchr_m(path+2,'\\');
793                 if (!q) {
794                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
795                         END_PROFILE(SMBtconX);
796                         return;
797                 }
798                 service = q+1;
799         } else {
800                 service = path;
801         }
802
803         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
804                                 &client_devicetype, p,
805                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
806
807         if (client_devicetype == NULL) {
808                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
809                 END_PROFILE(SMBtconX);
810                 return;
811         }
812
813         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
814
815         conn = make_connection(sconn, service, client_devicetype,
816                                req->vuid, &nt_status);
817         req->conn =conn;
818
819         if (!conn) {
820                 reply_nterror(req, nt_status);
821                 END_PROFILE(SMBtconX);
822                 return;
823         }
824
825         if ( IS_IPC(conn) )
826                 server_devicetype = "IPC";
827         else if ( IS_PRINT(conn) )
828                 server_devicetype = "LPT1:";
829         else
830                 server_devicetype = "A:";
831
832         if (get_Protocol() < PROTOCOL_NT1) {
833                 reply_outbuf(req, 2, 0);
834                 if (message_push_string(&req->outbuf, server_devicetype,
835                                         STR_TERMINATE|STR_ASCII) == -1) {
836                         reply_nterror(req, NT_STATUS_NO_MEMORY);
837                         END_PROFILE(SMBtconX);
838                         return;
839                 }
840         } else {
841                 /* NT sets the fstype of IPC$ to the null string */
842                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
843
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&nb