4d0a2b8c97dded0321e056072cf8fd5e0035e237
[ira/wip.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 "smbd/globals.h"
29
30 extern enum protocol_types Protocol;
31
32 /****************************************************************************
33  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34  path or anything including wildcards.
35  We're assuming here that '/' is not the second byte in any multibyte char
36  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37  set.
38 ****************************************************************************/
39
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
42
43 static NTSTATUS check_path_syntax_internal(char *path,
44                                            bool posix_path,
45                                            bool *p_last_component_contains_wcard)
46 {
47         char *d = path;
48         const char *s = path;
49         NTSTATUS ret = NT_STATUS_OK;
50         bool start_of_name_component = True;
51         bool stream_started = false;
52
53         *p_last_component_contains_wcard = False;
54
55         while (*s) {
56                 if (stream_started) {
57                         switch (*s) {
58                         case '/':
59                         case '\\':
60                                 return NT_STATUS_OBJECT_NAME_INVALID;
61                         case ':':
62                                 if (s[1] == '\0') {
63                                         return NT_STATUS_OBJECT_NAME_INVALID;
64                                 }
65                                 if (strchr_m(&s[1], ':')) {
66                                         return NT_STATUS_OBJECT_NAME_INVALID;
67                                 }
68                                 if (StrCaseCmp(s, ":$DATA") != 0) {
69                                         return NT_STATUS_INVALID_PARAMETER;
70                                 }
71                                 break;
72                         }
73                 }
74
75                 if (!posix_path && !stream_started && *s == ':') {
76                         if (*p_last_component_contains_wcard) {
77                                 return NT_STATUS_OBJECT_NAME_INVALID;
78                         }
79                         /* Stream names allow more characters than file names.
80                            We're overloading posix_path here to allow a wider
81                            range of characters. If stream_started is true this
82                            is still a Windows path even if posix_path is true.
83                            JRA.
84                         */
85                         stream_started = true;
86                         start_of_name_component = false;
87                         posix_path = true;
88
89                         if (s[1] == '\0') {
90                                 return NT_STATUS_OBJECT_NAME_INVALID;
91                         }
92                 }
93
94                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95                         /*
96                          * Safe to assume is not the second part of a mb char
97                          * as this is handled below.
98                          */
99                         /* Eat multiple '/' or '\\' */
100                         while (IS_PATH_SEP(*s,posix_path)) {
101                                 s++;
102                         }
103                         if ((d != path) && (*s != '\0')) {
104                                 /* We only care about non-leading or trailing '/' or '\\' */
105                                 *d++ = '/';
106                         }
107
108                         start_of_name_component = True;
109                         /* New component. */
110                         *p_last_component_contains_wcard = False;
111                         continue;
112                 }
113
114                 if (start_of_name_component) {
115                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
117
118                                 /*
119                                  * No mb char starts with '.' so we're safe checking the directory separator here.
120                                  */
121
122                                 /* If  we just added a '/' - delete it */
123                                 if ((d > path) && (*(d-1) == '/')) {
124                                         *(d-1) = '\0';
125                                         d--;
126                                 }
127
128                                 /* Are we at the start ? Can't go back further if so. */
129                                 if (d <= path) {
130                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
131                                         break;
132                                 }
133                                 /* Go back one level... */
134                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
135                                 /* NOTE - if this assumption is invalid we are not in good shape... */
136                                 /* Decrement d first as d points to the *next* char to write into. */
137                                 for (d--; d > path; d--) {
138                                         if (*d == '/')
139                                                 break;
140                                 }
141                                 s += 2; /* Else go past the .. */
142                                 /* We're still at the start of a name component, just the previous one. */
143                                 continue;
144
145                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
146                                 if (posix_path) {
147                                         /* Eat the '.' */
148                                         s++;
149                                         continue;
150                                 }
151                         }
152
153                 }
154
155                 if (!(*s & 0x80)) {
156                         if (!posix_path) {
157                                 if (*s <= 0x1f || *s == '|') {
158                                         return NT_STATUS_OBJECT_NAME_INVALID;
159                                 }
160                                 switch (*s) {
161                                         case '*':
162                                         case '?':
163                                         case '<':
164                                         case '>':
165                                         case '"':
166                                                 *p_last_component_contains_wcard = True;
167                                                 break;
168                                         default:
169                                                 break;
170                                 }
171                         }
172                         *d++ = *s++;
173                 } else {
174                         size_t siz;
175                         /* Get the size of the next MB character. */
176                         next_codepoint(s,&siz);
177                         switch(siz) {
178                                 case 5:
179                                         *d++ = *s++;
180                                         /*fall through*/
181                                 case 4:
182                                         *d++ = *s++;
183                                         /*fall through*/
184                                 case 3:
185                                         *d++ = *s++;
186                                         /*fall through*/
187                                 case 2:
188                                         *d++ = *s++;
189                                         /*fall through*/
190                                 case 1:
191                                         *d++ = *s++;
192                                         break;
193                                 default:
194                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195                                         *d = '\0';
196                                         return NT_STATUS_INVALID_PARAMETER;
197                         }
198                 }
199                 start_of_name_component = False;
200         }
201
202         *d = '\0';
203
204         return ret;
205 }
206
207 /****************************************************************************
208  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209  No wildcards allowed.
210 ****************************************************************************/
211
212 NTSTATUS check_path_syntax(char *path)
213 {
214         bool ignore;
215         return check_path_syntax_internal(path, False, &ignore);
216 }
217
218 /****************************************************************************
219  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220  Wildcards allowed - p_contains_wcard returns true if the last component contained
221  a wildcard.
222 ****************************************************************************/
223
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 {
226         return check_path_syntax_internal(path, False, p_contains_wcard);
227 }
228
229 /****************************************************************************
230  Check the path for a POSIX client.
231  We're assuming here that '/' is not the second byte in any multibyte char
232  set (a safe assumption).
233 ****************************************************************************/
234
235 NTSTATUS check_path_syntax_posix(char *path)
236 {
237         bool ignore;
238         return check_path_syntax_internal(path, True, &ignore);
239 }
240
241 /****************************************************************************
242  Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
244
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246                         const char *base_ptr,
247                         uint16 smb_flags2,
248                         char **pp_dest,
249                         const char *src,
250                         size_t src_len,
251                         int flags,
252                         NTSTATUS *err,
253                         bool *contains_wcard)
254 {
255         size_t ret;
256
257         *pp_dest = NULL;
258
259         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260                                  src_len, flags);
261
262         if (!*pp_dest) {
263                 *err = NT_STATUS_INVALID_PARAMETER;
264                 return ret;
265         }
266
267         *contains_wcard = False;
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /*
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(*pp_dest);
280         } else {
281                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Pull a string and check the path - provide for error return.
289 ****************************************************************************/
290
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292                         const char *base_ptr,
293                         uint16 smb_flags2,
294                         char **pp_dest,
295                         const char *src,
296                         size_t src_len,
297                         int flags,
298                         NTSTATUS *err)
299 {
300         bool ignore;
301         return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302                                      src_len, flags, err, &ignore);
303 }
304
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306                                  char **pp_dest, const char *src, int flags,
307                                  NTSTATUS *err, bool *contains_wcard)
308 {
309         return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310                                      pp_dest, src, smbreq_bufrem(req, src),
311                                      flags, err, contains_wcard);
312 }
313
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315                            char **pp_dest, const char *src, int flags,
316                            NTSTATUS *err)
317 {
318         bool ignore;
319         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320                                          flags, err, &ignore);
321 }
322
323 /****************************************************************************
324  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
326
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328                     files_struct *fsp)
329 {
330         if (!(fsp) || !(conn)) {
331                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332                 return False;
333         }
334         if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336                 return False;
337         }
338         return True;
339 }
340
341 /****************************************************************************
342  Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
344
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346                files_struct *fsp)
347 {
348         if (!check_fsp_open(conn, req, fsp)) {
349                 return False;
350         }
351         if ((fsp)->is_directory) {
352                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353                 return False;
354         }
355         if ((fsp)->fh->fd == -1) {
356                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357                 return False;
358         }
359         (fsp)->num_smb_operations++;
360         return True;
361 }
362
363 /****************************************************************************
364  Check if we have a correct fsp pointing to a quota fake file. Replacement for
365  the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
367
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369                               files_struct *fsp)
370 {
371         if (!check_fsp_open(conn, req, fsp)) {
372                 return false;
373         }
374
375         if (fsp->is_directory) {
376                 return false;
377         }
378
379         if (fsp->fake_file_handle == NULL) {
380                 return false;
381         }
382
383         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384                 return false;
385         }
386
387         if (fsp->fake_file_handle->private_data == NULL) {
388                 return false;
389         }
390
391         return true;
392 }
393
394 /****************************************************************************
395  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
397
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399                       files_struct *fsp)
400 {
401         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402             && (req->vuid == (fsp)->vuid)) {
403                 return True;
404         }
405
406         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407         return False;
408 }
409
410 static bool netbios_session_retarget(const char *name, int name_type)
411 {
412         char *trim_name;
413         char *trim_name_type;
414         const char *retarget_parm;
415         char *retarget;
416         char *p;
417         int retarget_type = 0x20;
418         int retarget_port = 139;
419         struct sockaddr_storage retarget_addr;
420         struct sockaddr_in *in_addr;
421         bool ret = false;
422         uint8_t outbuf[10];
423
424         if (get_socket_port(smbd_server_fd()) != 139) {
425                 return false;
426         }
427
428         trim_name = talloc_strdup(talloc_tos(), name);
429         if (trim_name == NULL) {
430                 goto fail;
431         }
432         trim_char(trim_name, ' ', ' ');
433
434         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
435                                          name_type);
436         if (trim_name_type == NULL) {
437                 goto fail;
438         }
439
440         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441                                              trim_name_type, NULL);
442         if (retarget_parm == NULL) {
443                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
444                                                      trim_name, NULL);
445         }
446         if (retarget_parm == NULL) {
447                 goto fail;
448         }
449
450         retarget = talloc_strdup(trim_name, retarget_parm);
451         if (retarget == NULL) {
452                 goto fail;
453         }
454
455         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
456
457         p = strchr(retarget, ':');
458         if (p != NULL) {
459                 *p++ = '\0';
460                 retarget_port = atoi(p);
461         }
462
463         p = strchr_m(retarget, '#');
464         if (p != NULL) {
465                 *p++ = '\0';
466                 sscanf(p, "%x", &retarget_type);
467         }
468
469         ret = resolve_name(retarget, &retarget_addr, retarget_type);
470         if (!ret) {
471                 DEBUG(10, ("could not resolve %s\n", retarget));
472                 goto fail;
473         }
474
475         if (retarget_addr.ss_family != AF_INET) {
476                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477                 goto fail;
478         }
479
480         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
481
482         _smb_setlen(outbuf, 6);
483         SCVAL(outbuf, 0, 0x84);
484         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485         *(uint16_t *)(outbuf+8) = htons(retarget_port);
486
487         if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
488                           NULL)) {
489                 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490                                     "failed.");
491         }
492
493         ret = true;
494  fail:
495         TALLOC_FREE(trim_name);
496         return ret;
497 }
498
499 /****************************************************************************
500  Reply to a (netbios-level) special message.
501 ****************************************************************************/
502
503 void reply_special(char *inbuf)
504 {
505         int msg_type = CVAL(inbuf,0);
506         int msg_flags = CVAL(inbuf,1);
507         fstring name1,name2;
508         char name_type1, name_type2;
509         struct smbd_server_connection *sconn = smbd_server_conn;
510
511         /*
512          * We only really use 4 bytes of the outbuf, but for the smb_setlen
513          * calculation & friends (srv_send_smb uses that) we need the full smb
514          * header.
515          */
516         char outbuf[smb_size];
517
518         *name1 = *name2 = 0;
519
520         memset(outbuf, '\0', sizeof(outbuf));
521
522         smb_setlen(outbuf,0);
523
524         switch (msg_type) {
525         case 0x81: /* session request */
526
527                 if (sconn->nbt.got_session) {
528                         exit_server_cleanly("multiple session request not permitted");
529                 }
530
531                 SCVAL(outbuf,0,0x82);
532                 SCVAL(outbuf,3,0);
533                 if (name_len(inbuf+4) > 50 || 
534                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535                         DEBUG(0,("Invalid name length in session request\n"));
536                         return;
537                 }
538                 name_type1 = name_extract(inbuf,4,name1);
539                 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541                          name1, name_type1, name2, name_type2));
542
543                 if (netbios_session_retarget(name1, name_type1)) {
544                         exit_server_cleanly("retargeted client");
545                 }
546
547                 set_local_machine_name(name1, True);
548                 set_remote_machine_name(name2, True);
549
550                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551                          get_local_machine_name(), get_remote_machine_name(),
552                          name_type2));
553
554                 if (name_type2 == 'R') {
555                         /* We are being asked for a pathworks session --- 
556                            no thanks! */
557                         SCVAL(outbuf, 0,0x83);
558                         break;
559                 }
560
561                 /* only add the client's machine name to the list
562                    of possibly valid usernames if we are operating
563                    in share mode security */
564                 if (lp_security() == SEC_SHARE) {
565                         add_session_user(sconn, get_remote_machine_name());
566                 }
567
568                 reload_services(True);
569                 reopen_logs();
570
571                 sconn->nbt.got_session = true;
572                 break;
573
574         case 0x89: /* session keepalive request 
575                       (some old clients produce this?) */
576                 SCVAL(outbuf,0,SMBkeepalive);
577                 SCVAL(outbuf,3,0);
578                 break;
579
580         case 0x82: /* positive session response */
581         case 0x83: /* negative session response */
582         case 0x84: /* retarget session response */
583                 DEBUG(0,("Unexpected session response\n"));
584                 break;
585
586         case SMBkeepalive: /* session keepalive */
587         default:
588                 return;
589         }
590
591         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592                     msg_type, msg_flags));
593
594         srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595         return;
596 }
597
598 /****************************************************************************
599  Reply to a tcon.
600  conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
602
603 void reply_tcon(struct smb_request *req)
604 {
605         connection_struct *conn = req->conn;
606         const char *service;
607         char *service_buf = NULL;
608         char *password = NULL;
609         char *dev = NULL;
610         int pwlen=0;
611         NTSTATUS nt_status;
612         const char *p;
613         DATA_BLOB password_blob;
614         TALLOC_CTX *ctx = talloc_tos();
615         struct smbd_server_connection *sconn = smbd_server_conn;
616
617         START_PROFILE(SMBtcon);
618
619         if (req->buflen < 4) {
620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621                 END_PROFILE(SMBtcon);
622                 return;
623         }
624
625         p = (const char *)req->buf + 1;
626         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627         p += 1;
628         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629         p += pwlen+1;
630         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631         p += 1;
632
633         if (service_buf == NULL || password == NULL || dev == NULL) {
634                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635                 END_PROFILE(SMBtcon);
636                 return;
637         }
638         p = strrchr_m(service_buf,'\\');
639         if (p) {
640                 service = p+1;
641         } else {
642                 service = service_buf;
643         }
644
645         password_blob = data_blob(password, pwlen+1);
646
647         conn = make_connection(sconn,service,password_blob,dev,
648                                req->vuid,&nt_status);
649         req->conn = conn;
650
651         data_blob_clear_free(&password_blob);
652
653         if (!conn) {
654                 reply_nterror(req, nt_status);
655                 END_PROFILE(SMBtcon);
656                 return;
657         }
658
659         reply_outbuf(req, 2, 0);
660         SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662         SSVAL(req->outbuf,smb_tid,conn->cnum);
663
664         DEBUG(3,("tcon service=%s cnum=%d\n",
665                  service, conn->cnum));
666
667         END_PROFILE(SMBtcon);
668         return;
669 }
670
671 /****************************************************************************
672  Reply to a tcon and X.
673  conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
675
676 void reply_tcon_and_X(struct smb_request *req)
677 {
678         connection_struct *conn = req->conn;
679         const char *service = NULL;
680         DATA_BLOB password;
681         TALLOC_CTX *ctx = talloc_tos();
682         /* what the cleint thinks the device is */
683         char *client_devicetype = NULL;
684         /* what the server tells the client the share represents */
685         const char *server_devicetype;
686         NTSTATUS nt_status;
687         int passlen;
688         char *path = NULL;
689         const char *p, *q;
690         uint16 tcon_flags;
691         struct smbd_server_connection *sconn = smbd_server_conn;
692
693         START_PROFILE(SMBtconX);
694
695         if (req->wct < 4) {
696                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697                 END_PROFILE(SMBtconX);
698                 return;
699         }
700
701         passlen = SVAL(req->vwv+3, 0);
702         tcon_flags = SVAL(req->vwv+2, 0);
703
704         /* we might have to close an old one */
705         if ((tcon_flags & 0x1) && conn) {
706                 close_cnum(sconn, conn,req->vuid);
707                 req->conn = NULL;
708                 conn = NULL;
709         }
710
711         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713                 END_PROFILE(SMBtconX);
714                 return;
715         }
716
717         if (sconn->smb1.negprot.encrypted_passwords) {
718                 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719                 if (lp_security() == SEC_SHARE) {
720                         /*
721                          * Security = share always has a pad byte
722                          * after the password.
723                          */
724                         p = (const char *)req->buf + passlen + 1;
725                 } else {
726                         p = (const char *)req->buf + passlen;
727                 }
728         } else {
729                 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730                 /* Ensure correct termination */
731                 password.data[passlen]=0;
732                 p = (const char *)req->buf + passlen + 1;
733         }
734
735         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
736
737         if (path == NULL) {
738                 data_blob_clear_free(&password);
739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740                 END_PROFILE(SMBtconX);
741                 return;
742         }
743
744         /*
745          * the service name can be either: \\server\share
746          * or share directly like on the DELL PowerVault 705
747          */
748         if (*path=='\\') {
749                 q = strchr_m(path+2,'\\');
750                 if (!q) {
751                         data_blob_clear_free(&password);
752                         reply_doserror(req, ERRDOS, ERRnosuchshare);
753                         END_PROFILE(SMBtconX);
754                         return;
755                 }
756                 service = q+1;
757         } else {
758                 service = path;
759         }
760
761         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762                                 &client_devicetype, p,
763                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
764
765         if (client_devicetype == NULL) {
766                 data_blob_clear_free(&password);
767                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768                 END_PROFILE(SMBtconX);
769                 return;
770         }
771
772         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
773
774         conn = make_connection(sconn, service, password, client_devicetype,
775                                req->vuid, &nt_status);
776         req->conn =conn;
777
778         data_blob_clear_free(&password);
779
780         if (!conn) {
781                 reply_nterror(req, nt_status);
782                 END_PROFILE(SMBtconX);
783                 return;
784         }
785
786         if ( IS_IPC(conn) )
787                 server_devicetype = "IPC";
788         else if ( IS_PRINT(conn) )
789                 server_devicetype = "LPT1:";
790         else
791                 server_devicetype = "A:";
792
793         if (Protocol < PROTOCOL_NT1) {
794                 reply_outbuf(req, 2, 0);
795                 if (message_push_string(&req->outbuf, server_devicetype,
796                                         STR_TERMINATE|STR_ASCII) == -1) {
797                         reply_nterror(req, NT_STATUS_NO_MEMORY);
798                         END_PROFILE(SMBtconX);
799                         return;
800                 }
801         } else {
802                 /* NT sets the fstype of IPC$ to the null string */
803                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
804
805                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806                         /* Return permissions. */
807                         uint32 perm1 = 0;
808                         uint32 perm2 = 0;
809
810                         reply_outbuf(req, 7, 0);
811
812                         if (IS_IPC(conn)) {
813                                 perm1 = FILE_ALL_ACCESS;
814                                 perm2 = FILE_ALL_ACCESS;
815                         } else {
816                                 perm1 = CAN_WRITE(conn) ?
817                                                 SHARE_ALL_ACCESS :
818                                                 SHARE_READ_ONLY;
819                         }
820
821                         SIVAL(req->outbuf, smb_vwv3, perm1);
822                         SIVAL(req->outbuf, smb_vwv5, perm2);
823                 } else {
824                         reply_outbuf(req, 3, 0);
825                 }
826
827                 if ((message_push_string(&req->outbuf, server_devicetype,
828                                          STR_TERMINATE|STR_ASCII) == -1)
829                     || (message_push_string(&req->outbuf, fstype,
830                                             STR_TERMINATE) == -1)) {
831                         reply_nterror(req, NT_STATUS_NO_MEMORY);
832                         END_PROFILE(SMBtconX);
833                         return;
834                 }
835
836                 /* what does setting this bit do? It is set by NT4 and
837                    may affect the ability to autorun mounted cdroms */
838                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839                       (lp_csc_policy(SNUM(conn)) << 2));
840
841                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842                         DEBUG(2,("Serving %s as a Dfs root\n",
843                                  lp_servicename(SNUM(conn)) ));
844                         SSVAL(req->outbuf, smb_vwv2,
845                               SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846                 }
847         }
848
849
850         DEBUG(3,("tconX service=%s \n",
851                  service));
852
853         /* set the incoming and outgoing tid to the just created one */
854         SSVAL(req->inbuf,smb_tid,conn->cnum);
855         SSVAL(req->outbuf,smb_tid,conn->cnum);
856
857         END_PROFILE(SMBtconX);
858
859         chain_reply(req);
860         return;
861 }
862
863 /****************************************************************************
864  Reply to an unknown type.
865 ****************************************************************************/
866
867 void reply_unknown_new(struct smb_request *req, uint8 type)
868 {
869         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
870                   smb_fn_name(type), type, type));
871         reply_doserror(req, ERRSRV, ERRunknownsmb);
872         return;
873 }
874
875 /****************************************************************************
876  Reply to an ioctl.
877  conn POINTER CAN BE NULL HERE !
878 ****************************************************************************/
879
880 void reply_ioctl(struct smb_request *req)
881 {
882         connection_struct *conn = req->conn;
883         uint16 device;
884         uint16 function;
885         uint32 ioctl_code;
886         int replysize;
887         char *p;
888
889         START_PROFILE(SMBioctl);
890
891         if (req->wct < 3) {
892                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893                 END_PROFILE(SMBioctl);
894                 return;
895         }
896
897         device     = SVAL(req->vwv+1, 0);
898         function   = SVAL(req->vwv+2, 0);
899         ioctl_code = (device << 16) + function;
900
901         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
902
903         switch (ioctl_code) {
904             case IOCTL_QUERY_JOB_INFO:
905                     replysize = 32;
906                     break;
907             default:
908                     reply_doserror(req, ERRSRV, ERRnosupport);
909                     END_PROFILE(SMBioctl);
910                     return;
911         }
912
913         reply_outbuf(req, 8, replysize+1);
914         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
915         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
916         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
917         p = smb_buf(req->outbuf);
918         memset(p, '\0', replysize+1); /* valgrind-safe. */
919         p += 1;          /* Allow for alignment */
920
921         switch (ioctl_code) {
922                 case IOCTL_QUERY_JOB_INFO:                  
923                 {
924                         files_struct *fsp = file_fsp(
925                                 req, SVAL(req->vwv+0, 0));
926                         if (!fsp) {
927                                 reply_doserror(req, ERRDOS, ERRbadfid);
928                                 END_PROFILE(SMBioctl);
929                                 return;
930                         }
931                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
932                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
933                                     global_myname(), 15,
934                                     STR_TERMINATE|STR_ASCII);
935                         if (conn) {
936                                 srvstr_push((char *)req->outbuf, req->flags2,
937                                             p+18, lp_servicename(SNUM(conn)),
938                                             13, STR_TERMINATE|STR_ASCII);
939                         } else {
940                                 memset(p+18, 0, 13);
941                         }
942                         break;
943                 }
944         }
945
946         END_PROFILE(SMBioctl);
947         return;
948 }
949
950 /****************************************************************************
951  Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
953
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
955 {
956         /* Strange DOS error code semantics only for checkpath... */
957         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959                         /* We need to map to ERRbadpath */
960                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
961                 }
962         }
963         return status;
964 }
965
966 /****************************************************************************
967  Reply to a checkpath.
968 ****************************************************************************/
969
970 void reply_checkpath(struct smb_request *req)
971 {
972         connection_struct *conn = req->conn;
973         struct smb_filename *smb_fname = NULL;
974         char *name = NULL;
975         NTSTATUS status;
976         TALLOC_CTX *ctx = talloc_tos();
977
978         START_PROFILE(SMBcheckpath);
979
980         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981                             STR_TERMINATE, &status);
982
983         if (!NT_STATUS_IS_OK(status)) {
984                 status = map_checkpath_error(req->flags2, status);
985                 reply_nterror(req, status);
986                 END_PROFILE(SMBcheckpath);
987                 return;
988         }
989
990         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
991
992         status = filename_convert(ctx,
993                                 conn,
994                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
995                                 name,
996                                 &smb_fname,
997                                 NULL);
998
999         if (!NT_STATUS_IS_OK(status)) {
1000                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1001                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1002                                         ERRSRV, ERRbadpath);
1003                         END_PROFILE(SMBcheckpath);
1004                         return;
1005                 }
1006                 goto path_err;
1007         }
1008
1009         if (!VALID_STAT(smb_fname->st) &&
1010             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1011                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1012                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1013                 status = map_nt_error_from_unix(errno);
1014                 goto path_err;
1015         }
1016
1017         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1018                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1019                                 ERRDOS, ERRbadpath);
1020                 goto out;
1021         }
1022
1023         reply_outbuf(req, 0, 0);
1024
1025  path_err:
1026         /* We special case this - as when a Windows machine
1027                 is parsing a path is steps through the components
1028                 one at a time - if a component fails it expects
1029                 ERRbadpath, not ERRbadfile.
1030         */
1031         status = map_checkpath_error(req->flags2, status);
1032         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1033                 /*
1034                  * Windows returns different error codes if
1035                  * the parent directory is valid but not the
1036                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1037                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1038                  * if the path is invalid.
1039                  */
1040                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1041                                 ERRDOS, ERRbadpath);
1042                 goto out;
1043         }
1044
1045         reply_nterror(req, status);
1046
1047  out:
1048         TALLOC_FREE(smb_fname);
1049         END_PROFILE(SMBcheckpath);
1050         return;
1051 }
1052
1053 /****************************************************************************
1054  Reply to a getatr.
1055 ****************************************************************************/
1056
1057 void reply_getatr(struct smb_request *req)
1058 {
1059         connection_struct *conn = req->conn;
1060         struct smb_filename *smb_fname = NULL;
1061         char *fname = NULL;
1062         int mode=0;
1063         SMB_OFF_T size=0;
1064         time_t mtime=0;
1065         const char *p;
1066         NTSTATUS status;
1067         TALLOC_CTX *ctx = talloc_tos();
1068         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1069
1070         START_PROFILE(SMBgetatr);
1071
1072         p = (const char *)req->buf + 1;
1073         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1074         if (!NT_STATUS_IS_OK(status)) {
1075                 reply_nterror(req, status);
1076                 goto out;
1077         }
1078
1079         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1080                 under WfWg - weird! */
1081         if (*fname == '\0') {
1082                 mode = aHIDDEN | aDIR;
1083                 if (!CAN_WRITE(conn)) {
1084                         mode |= aRONLY;
1085                 }
1086                 size = 0;
1087                 mtime = 0;
1088         } else {
1089                 status = filename_convert(ctx,
1090                                 conn,
1091                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092                                 fname,
1093                                 &smb_fname,
1094                                 NULL);
1095                 if (!NT_STATUS_IS_OK(status)) {
1096                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1097                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1098                                                 ERRSRV, ERRbadpath);
1099                                 goto out;
1100                         }
1101                         reply_nterror(req, status);
1102                         goto out;
1103                 }
1104                 if (!VALID_STAT(smb_fname->st) &&
1105                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1106                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1107                                  smb_fname_str_dbg(smb_fname),
1108                                  strerror(errno)));
1109                         reply_nterror(req,  map_nt_error_from_unix(errno));
1110                         goto out;
1111                 }
1112
1113                 mode = dos_mode(conn, smb_fname);
1114                 size = smb_fname->st.st_ex_size;
1115
1116                 if (ask_sharemode) {
1117                         struct timespec write_time_ts;
1118                         struct file_id fileid;
1119
1120                         ZERO_STRUCT(write_time_ts);
1121                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1122                         get_file_infos(fileid, NULL, &write_time_ts);
1123                         if (!null_timespec(write_time_ts)) {
1124                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1125                         }
1126                 }
1127
1128                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1129                 if (mode & aDIR) {
1130                         size = 0;
1131                 }
1132         }
1133
1134         reply_outbuf(req, 10, 0);
1135
1136         SSVAL(req->outbuf,smb_vwv0,mode);
1137         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1138                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1139         } else {
1140                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1141         }
1142         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1143
1144         if (Protocol >= PROTOCOL_NT1) {
1145                 SSVAL(req->outbuf, smb_flg2,
1146                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1147         }
1148
1149         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1150                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1151
1152  out:
1153         TALLOC_FREE(smb_fname);
1154         TALLOC_FREE(fname);
1155         END_PROFILE(SMBgetatr);
1156         return;
1157 }
1158
1159 /****************************************************************************
1160  Reply to a setatr.
1161 ****************************************************************************/
1162
1163 void reply_setatr(struct smb_request *req)
1164 {
1165         struct smb_file_time ft;
1166         connection_struct *conn = req->conn;
1167         struct smb_filename *smb_fname = NULL;
1168         char *fname = NULL;
1169         int mode;
1170         time_t mtime;
1171         const char *p;
1172         NTSTATUS status;
1173         TALLOC_CTX *ctx = talloc_tos();
1174
1175         START_PROFILE(SMBsetatr);
1176
1177         ZERO_STRUCT(ft);
1178
1179         if (req->wct < 2) {
1180                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1181                 goto out;
1182         }
1183
1184         p = (const char *)req->buf + 1;
1185         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 reply_nterror(req, status);
1188                 goto out;
1189         }
1190
1191         status = filename_convert(ctx,
1192                                 conn,
1193                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1194                                 fname,
1195                                 &smb_fname,
1196                                 NULL);
1197         if (!NT_STATUS_IS_OK(status)) {
1198                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1199                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1200                                         ERRSRV, ERRbadpath);
1201                         goto out;
1202                 }
1203                 reply_nterror(req, status);
1204                 goto out;
1205         }
1206
1207         if (smb_fname->base_name[0] == '.' &&
1208             smb_fname->base_name[1] == '\0') {
1209                 /*
1210                  * Not sure here is the right place to catch this
1211                  * condition. Might be moved to somewhere else later -- vl
1212                  */
1213                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1214                 goto out;
1215         }
1216
1217         mode = SVAL(req->vwv+0, 0);
1218         mtime = srv_make_unix_date3(req->vwv+1);
1219
1220         ft.mtime = convert_time_t_to_timespec(mtime);
1221         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1222         if (!NT_STATUS_IS_OK(status)) {
1223                 reply_nterror(req, status);
1224                 goto out;
1225         }
1226
1227         if (mode != FILE_ATTRIBUTE_NORMAL) {
1228                 if (VALID_STAT_OF_DIR(smb_fname->st))
1229                         mode |= aDIR;
1230                 else
1231                         mode &= ~aDIR;
1232
1233                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1234                                      false) != 0) {
1235                         reply_nterror(req, map_nt_error_from_unix(errno));
1236                         goto out;
1237                 }
1238         }
1239
1240         reply_outbuf(req, 0, 0);
1241
1242         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1243                  mode));
1244  out:
1245         TALLOC_FREE(smb_fname);
1246         END_PROFILE(SMBsetatr);
1247         return;
1248 }
1249
1250 /****************************************************************************
1251  Reply to a dskattr.
1252 ****************************************************************************/
1253
1254 void reply_dskattr(struct smb_request *req)
1255 {
1256         connection_struct *conn = req->conn;
1257         uint64_t dfree,dsize,bsize;
1258         START_PROFILE(SMBdskattr);
1259
1260         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1261                 reply_nterror(req, map_nt_error_from_unix(errno));
1262                 END_PROFILE(SMBdskattr);
1263                 return;
1264         }
1265
1266         reply_outbuf(req, 5, 0);
1267
1268         if (Protocol <= PROTOCOL_LANMAN2) {
1269                 double total_space, free_space;
1270                 /* we need to scale this to a number that DOS6 can handle. We
1271                    use floating point so we can handle large drives on systems
1272                    that don't have 64 bit integers 
1273
1274                    we end up displaying a maximum of 2G to DOS systems
1275                 */
1276                 total_space = dsize * (double)bsize;
1277                 free_space = dfree * (double)bsize;
1278
1279                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1280                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1281
1282                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1283                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1284
1285                 SSVAL(req->outbuf,smb_vwv0,dsize);
1286                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1287                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1288                 SSVAL(req->outbuf,smb_vwv3,dfree);
1289         } else {
1290                 SSVAL(req->outbuf,smb_vwv0,dsize);
1291                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1292                 SSVAL(req->outbuf,smb_vwv2,512);
1293                 SSVAL(req->outbuf,smb_vwv3,dfree);
1294         }
1295
1296         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1297
1298         END_PROFILE(SMBdskattr);
1299         return;
1300 }
1301
1302 /*
1303  * Utility function to split the filename from the directory.
1304  */
1305 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1306                                      char **fname_dir_out,
1307                                      char **fname_mask_out)
1308 {
1309         const char *p = NULL;
1310         char *fname_dir = NULL;
1311         char *fname_mask = NULL;
1312
1313         p = strrchr_m(fname_in, '/');
1314         if (!p) {
1315                 fname_dir = talloc_strdup(ctx, ".");
1316                 fname_mask = talloc_strdup(ctx, fname_in);
1317         } else {
1318                 fname_dir = talloc_strndup(ctx, fname_in,
1319                     PTR_DIFF(p, fname_in));
1320                 fname_mask = talloc_strdup(ctx, p+1);
1321         }
1322
1323         if (!fname_dir || !fname_mask) {
1324                 TALLOC_FREE(fname_dir);
1325                 TALLOC_FREE(fname_mask);
1326                 return NT_STATUS_NO_MEMORY;
1327         }
1328
1329         *fname_dir_out = fname_dir;
1330         *fname_mask_out = fname_mask;
1331         return NT_STATUS_OK;
1332 }
1333
1334 /****************************************************************************
1335  Reply to a search.
1336  Can be called from SMBsearch, SMBffirst or SMBfunique.
1337 ****************************************************************************/
1338
1339 void reply_search(struct smb_request *req)
1340 {
1341         connection_struct *conn = req->conn;
1342         char *path = NULL;
1343         const char *mask = NULL;
1344         char *directory = NULL;
1345         char *fname = NULL;
1346         SMB_OFF_T size;
1347         uint32 mode;
1348         struct timespec date;
1349         uint32 dirtype;
1350         unsigned int numentries = 0;
1351         unsigned int maxentries = 0;
1352         bool finished = False;
1353         const char *p;
1354         int status_len;
1355         char status[21];
1356         int dptr_num= -1;
1357         bool check_descend = False;
1358         bool expect_close = False;
1359         NTSTATUS nt_status;
1360         bool mask_contains_wcard = False;
1361         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1362         TALLOC_CTX *ctx = talloc_tos();
1363         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1364
1365         START_PROFILE(SMBsearch);
1366
1367         if (req->wct < 2) {
1368                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1369                 END_PROFILE(SMBsearch);
1370                 return;
1371         }
1372
1373         if (lp_posix_pathnames()) {
1374                 reply_unknown_new(req, req->cmd);
1375                 END_PROFILE(SMBsearch);
1376                 return;
1377         }
1378
1379         /* If we were called as SMBffirst then we must expect close. */
1380         if(req->cmd == SMBffirst) {
1381                 expect_close = True;
1382         }
1383
1384         reply_outbuf(req, 1, 3);
1385         maxentries = SVAL(req->vwv+0, 0);
1386         dirtype = SVAL(req->vwv+1, 0);
1387         p = (const char *)req->buf + 1;
1388         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1389                                        &nt_status, &mask_contains_wcard);
1390         if (!NT_STATUS_IS_OK(nt_status)) {
1391                 reply_nterror(req, nt_status);
1392                 END_PROFILE(SMBsearch);
1393                 return;
1394         }
1395
1396         p++;
1397         status_len = SVAL(p, 0);
1398         p += 2;
1399
1400         /* dirtype &= ~aDIR; */
1401
1402         if (status_len == 0) {
1403                 struct smb_filename *smb_fname = NULL;
1404
1405                 nt_status = resolve_dfspath_wcard(ctx, conn,
1406                                           req->flags2 & FLAGS2_DFS_PATHNAMES,
1407                                           path,
1408                                           &path,
1409                                           &mask_contains_wcard);
1410                 if (!NT_STATUS_IS_OK(nt_status)) {
1411                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1412                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1413                                                 ERRSRV, ERRbadpath);
1414                                 END_PROFILE(SMBsearch);
1415                                 return;
1416                         }
1417                         reply_nterror(req, nt_status);
1418                         END_PROFILE(SMBsearch);
1419                         return;
1420                 }
1421
1422                 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1423                                          UCF_ALLOW_WCARD_LCOMP);
1424                 if (!NT_STATUS_IS_OK(nt_status)) {
1425                         reply_nterror(req, nt_status);
1426                         END_PROFILE(SMBsearch);
1427                         return;
1428                 }
1429
1430                 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1431                 TALLOC_FREE(smb_fname);
1432                 if (!NT_STATUS_IS_OK(nt_status)) {
1433                         reply_nterror(req, nt_status);
1434                         END_PROFILE(SMBsearch);
1435                         return;
1436                 }
1437
1438                 nt_status = check_name(conn, directory);
1439                 if (!NT_STATUS_IS_OK(nt_status)) {
1440                         reply_nterror(req, nt_status);
1441                         END_PROFILE(SMBsearch);
1442                         return;
1443                 }
1444
1445                 p = strrchr_m(directory,'/');
1446                 if ((p != NULL) && (*directory != '/')) {
1447                         mask = p + 1;
1448                         directory = talloc_strndup(ctx, directory,
1449                                                    PTR_DIFF(p, directory));
1450                 } else {
1451                         mask = directory;
1452                         directory = talloc_strdup(ctx,".");
1453                 }
1454
1455                 if (!directory) {
1456                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1457                         END_PROFILE(SMBsearch);
1458                         return;
1459                 }
1460
1461                 memset((char *)status,'\0',21);
1462                 SCVAL(status,0,(dirtype & 0x1F));
1463
1464                 nt_status = dptr_create(conn,
1465                                         directory,
1466                                         True,
1467                                         expect_close,
1468                                         req->smbpid,
1469                                         mask,
1470                                         mask_contains_wcard,
1471                                         dirtype,
1472                                         &conn->dirptr);
1473                 if (!NT_STATUS_IS_OK(nt_status)) {
1474                         reply_nterror(req, nt_status);
1475                         END_PROFILE(SMBsearch);
1476                         return;
1477                 }
1478                 dptr_num = dptr_dnum(conn->dirptr);
1479         } else {
1480                 int status_dirtype;
1481
1482                 memcpy(status,p,21);
1483                 status_dirtype = CVAL(status,0) & 0x1F;
1484                 if (status_dirtype != (dirtype & 0x1F)) {
1485                         dirtype = status_dirtype;
1486                 }
1487
1488                 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1489                 if (!conn->dirptr) {
1490                         goto SearchEmpty;
1491                 }
1492                 string_set(&conn->dirpath,dptr_path(dptr_num));
1493                 mask = dptr_wcard(dptr_num);
1494                 if (!mask) {
1495                         goto SearchEmpty;
1496                 }
1497                 /*
1498                  * For a 'continue' search we have no string. So
1499                  * check from the initial saved string.
1500                  */
1501                 mask_contains_wcard = ms_has_wild(mask);
1502                 dirtype = dptr_attr(dptr_num);
1503         }
1504
1505         DEBUG(4,("dptr_num is %d\n",dptr_num));
1506
1507         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1508         dptr_init_search_op(conn->dirptr);
1509
1510         if ((dirtype&0x1F) == aVOLID) {
1511                 char buf[DIR_STRUCT_SIZE];
1512                 memcpy(buf,status,21);
1513                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1514                                 0,aVOLID,0,!allow_long_path_components)) {
1515                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1516                         END_PROFILE(SMBsearch);
1517                         return;
1518                 }
1519                 dptr_fill(buf+12,dptr_num);
1520                 if (dptr_zero(buf+12) && (status_len==0)) {
1521                         numentries = 1;
1522                 } else {
1523                         numentries = 0;
1524                 }
1525                 if (message_push_blob(&req->outbuf,
1526                                       data_blob_const(buf, sizeof(buf)))
1527                     == -1) {
1528                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1529                         END_PROFILE(SMBsearch);
1530                         return;
1531                 }
1532         } else {
1533                 unsigned int i;
1534                 maxentries = MIN(
1535                         maxentries,
1536                         ((BUFFER_SIZE -
1537                           ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1538                          /DIR_STRUCT_SIZE));
1539
1540                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1541                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1542                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1543                         check_descend = True;
1544                 }
1545
1546                 for (i=numentries;(i<maxentries) && !finished;i++) {
1547                         finished = !get_dir_entry(ctx,
1548                                                   conn,
1549                                                   mask,
1550                                                   dirtype,
1551                                                   &fname,
1552                                                   &size,
1553                                                   &mode,
1554                                                   &date,
1555                                                   check_descend,
1556                                                   ask_sharemode);
1557                         if (!finished) {
1558                                 char buf[DIR_STRUCT_SIZE];
1559                                 memcpy(buf,status,21);
1560                                 if (!make_dir_struct(ctx,
1561                                                 buf,
1562                                                 mask,
1563                                                 fname,
1564                                                 size,
1565                                                 mode,
1566                                                 convert_timespec_to_time_t(date),
1567                                                 !allow_long_path_components)) {
1568                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1569                                         END_PROFILE(SMBsearch);
1570                                         return;
1571                                 }
1572                                 if (!dptr_fill(buf+12,dptr_num)) {
1573                                         break;
1574                                 }
1575                                 if (message_push_blob(&req->outbuf,
1576                                                       data_blob_const(buf, sizeof(buf)))
1577                                     == -1) {
1578                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1579                                         END_PROFILE(SMBsearch);
1580                                         return;
1581                                 }
1582                                 numentries++;
1583                         }
1584                 }
1585         }
1586
1587   SearchEmpty:
1588
1589         /* If we were called as SMBffirst with smb_search_id == NULL
1590                 and no entries were found then return error and close dirptr 
1591                 (X/Open spec) */
1592
1593         if (numentries == 0) {
1594                 dptr_close(&dptr_num);
1595         } else if(expect_close && status_len == 0) {
1596                 /* Close the dptr - we know it's gone */
1597                 dptr_close(&dptr_num);
1598         }
1599
1600         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1601         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1602                 dptr_close(&dptr_num);
1603         }
1604
1605         if ((numentries == 0) && !mask_contains_wcard) {
1606                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1607                 END_PROFILE(SMBsearch);
1608                 return;
1609         }
1610
1611         SSVAL(req->outbuf,smb_vwv0,numentries);
1612         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1613         SCVAL(smb_buf(req->outbuf),0,5);
1614         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1615
1616         /* The replies here are never long name. */
1617         SSVAL(req->outbuf, smb_flg2,
1618               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1619         if (!allow_long_path_components) {
1620                 SSVAL(req->outbuf, smb_flg2,
1621                       SVAL(req->outbuf, smb_flg2)
1622                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1623         }
1624
1625         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1626         SSVAL(req->outbuf, smb_flg2,
1627               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1628
1629         if (!directory) {
1630                 directory = dptr_path(dptr_num);
1631         }
1632
1633         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1634                 smb_fn_name(req->cmd),
1635                 mask,
1636                 directory ? directory : "./",
1637                 dirtype,
1638                 numentries,
1639                 maxentries ));
1640
1641         END_PROFILE(SMBsearch);
1642         return;
1643 }
1644
1645 /****************************************************************************
1646  Reply to a fclose (stop directory search).
1647 ****************************************************************************/
1648
1649 void reply_fclose(struct smb_request *req)
1650 {
1651         int status_len;
1652         char status[21];
1653         int dptr_num= -2;
1654         const char *p;
1655         char *path = NULL;
1656         NTSTATUS err;
1657         bool path_contains_wcard = False;
1658         TALLOC_CTX *ctx = talloc_tos();
1659
1660         START_PROFILE(SMBfclose);
1661
1662         if (lp_posix_pathnames()) {
1663                 reply_unknown_new(req, req->cmd);
1664                 END_PROFILE(SMBfclose);
1665                 return;
1666         }
1667
1668         p = (const char *)req->buf + 1;
1669         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1670                                        &err, &path_contains_wcard);
1671         if (!NT_STATUS_IS_OK(err)) {
1672                 reply_nterror(req, err);
1673                 END_PROFILE(SMBfclose);
1674                 return;
1675         }
1676         p++;
1677         status_len = SVAL(p,0);
1678         p += 2;
1679
1680         if (status_len == 0) {
1681                 reply_doserror(req, ERRSRV, ERRsrverror);
1682                 END_PROFILE(SMBfclose);
1683                 return;
1684         }
1685
1686         memcpy(status,p,21);
1687
1688         if(dptr_fetch(status+12,&dptr_num)) {
1689                 /*  Close the dptr - we know it's gone */
1690                 dptr_close(&dptr_num);
1691         }
1692
1693         reply_outbuf(req, 1, 0);
1694         SSVAL(req->outbuf,smb_vwv0,0);
1695
1696         DEBUG(3,("search close\n"));
1697
1698         END_PROFILE(SMBfclose);
1699         return;
1700 }
1701
1702 /****************************************************************************
1703  Reply to an open.
1704 ****************************************************************************/
1705
1706 void reply_open(struct smb_request *req)
1707 {
1708         connection_struct *conn = req->conn;
1709         struct smb_filename *smb_fname = NULL;
1710         char *fname = NULL;
1711         uint32 fattr=0;
1712         SMB_OFF_T size = 0;
1713         time_t mtime=0;
1714         int info;
1715         files_struct *fsp;
1716         int oplock_request;
1717         int deny_mode;
1718         uint32 dos_attr;
1719         uint32 access_mask;
1720         uint32 share_mode;
1721         uint32 create_disposition;
1722         uint32 create_options = 0;
1723         NTSTATUS status;
1724         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1725         TALLOC_CTX *ctx = talloc_tos();
1726
1727         START_PROFILE(SMBopen);
1728
1729         if (req->wct < 2) {
1730                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1731                 goto out;
1732         }
1733
1734         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1735         deny_mode = SVAL(req->vwv+0, 0);
1736         dos_attr = SVAL(req->vwv+1, 0);
1737
1738         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1739                             STR_TERMINATE, &status);
1740         if (!NT_STATUS_IS_OK(status)) {
1741                 reply_nterror(req, status);
1742                 goto out;
1743         }
1744
1745         status = filename_convert(ctx,
1746                                 conn,
1747                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1748                                 fname,
1749                                 &smb_fname,
1750                                 NULL);
1751         if (!NT_STATUS_IS_OK(status)) {
1752                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1753                         reply_botherror(req,
1754                                         NT_STATUS_PATH_NOT_COVERED,
1755                                         ERRSRV, ERRbadpath);
1756                         goto out;
1757                 }
1758                 reply_nterror(req, status);
1759                 goto out;
1760         }
1761
1762         if (!map_open_params_to_ntcreate(
1763                     smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN,
1764                     &access_mask, &share_mode, &create_disposition,
1765                     &create_options)) {
1766                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1767                 goto out;
1768         }
1769
1770         status = SMB_VFS_CREATE_FILE(
1771                 conn,                                   /* conn */
1772                 req,                                    /* req */
1773                 0,                                      /* root_dir_fid */
1774                 smb_fname,                              /* fname */
1775                 access_mask,                            /* access_mask */
1776                 share_mode,                             /* share_access */
1777                 create_disposition,                     /* create_disposition*/
1778                 create_options,                         /* create_options */
1779                 dos_attr,                               /* file_attributes */
1780                 oplock_request,                         /* oplock_request */
1781                 0,                                      /* allocation_size */
1782                 NULL,                                   /* sd */
1783                 NULL,                                   /* ea_list */
1784                 &fsp,                                   /* result */
1785                 &info);                                 /* pinfo */
1786
1787         if (!NT_STATUS_IS_OK(status)) {
1788                 if (open_was_deferred(req->mid)) {
1789                         /* We have re-scheduled this call. */
1790                         goto out;
1791                 }
1792                 reply_openerror(req, status);
1793                 goto out;
1794         }
1795
1796         size = smb_fname->st.st_ex_size;
1797         fattr = dos_mode(conn, smb_fname);
1798
1799         /* Deal with other possible opens having a modified
1800            write time. JRA. */
1801         if (ask_sharemode) {
1802                 struct timespec write_time_ts;
1803
1804                 ZERO_STRUCT(write_time_ts);
1805                 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1806                 if (!null_timespec(write_time_ts)) {
1807                         update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1808                 }
1809         }
1810
1811         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1812
1813         if (fattr & aDIR) {
1814                 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1815                 close_file(req, fsp, ERROR_CLOSE);
1816                 reply_doserror(req, ERRDOS,ERRnoaccess);
1817                 goto out;
1818         }
1819
1820         reply_outbuf(req, 7, 0);
1821         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1822         SSVAL(req->outbuf,smb_vwv1,fattr);
1823         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1824                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1825         } else {
1826                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1827         }
1828         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1829         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1830
1831         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1832                 SCVAL(req->outbuf,smb_flg,
1833                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1834         }
1835
1836         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1837                 SCVAL(req->outbuf,smb_flg,
1838                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1839         }
1840  out:
1841         TALLOC_FREE(smb_fname);
1842         END_PROFILE(SMBopen);
1843         return;
1844 }
1845
1846 /****************************************************************************
1847  Reply to an open and X.
1848 ****************************************************************************/
1849
1850 void reply_open_and_X(struct smb_request *req)
1851 {
1852         connection_struct *conn = req->conn;
1853         struct smb_filename *smb_fname = NULL;
1854         char *fname = NULL;
1855         uint16 open_flags;
1856         int deny_mode;
1857         uint32 smb_attr;
1858         /* Breakout the oplock request bits so we can set the
1859                 reply bits separately. */
1860         int ex_oplock_request;
1861         int core_oplock_request;
1862         int oplock_request;
1863 #if 0
1864         int smb_sattr = SVAL(req->vwv+4, 0);
1865         uint32 smb_time = make_unix_date3(req->vwv+6);
1866 #endif
1867         int smb_ofun;
1868         uint32 fattr=0;
1869         int mtime=0;
1870         int smb_action = 0;
1871         files_struct *fsp;
1872         NTSTATUS status;
1873         uint64_t allocation_size;
1874         ssize_t retval = -1;
1875         uint32 access_mask;
1876         uint32 share_mode;
1877         uint32 create_disposition;
1878         uint32 create_options = 0;
1879         TALLOC_CTX *ctx = talloc_tos();
1880
1881         START_PROFILE(SMBopenX);
1882
1883         if (req->wct < 15) {
1884                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1885                 goto out;
1886         }
1887
1888         open_flags = SVAL(req->vwv+2, 0);
1889         deny_mode = SVAL(req->vwv+3, 0);
1890         smb_attr = SVAL(req->vwv+5, 0);
1891         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1892         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1893         oplock_request = ex_oplock_request | core_oplock_request;
1894         smb_ofun = SVAL(req->vwv+8, 0);
1895         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1896
1897         /* If it's an IPC, pass off the pipe handler. */
1898         if (IS_IPC(conn)) {
1899                 if (lp_nt_pipe_support()) {
1900                         reply_open_pipe_and_X(conn, req);
1901                 } else {
1902                         reply_doserror(req, ERRSRV, ERRaccess);
1903                 }
1904                 goto out;
1905         }
1906
1907         /* XXXX we need to handle passed times, sattr and flags */
1908         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1909                         STR_TERMINATE, &status);
1910         if (!NT_STATUS_IS_OK(status)) {
1911                 reply_nterror(req, status);
1912                 goto out;
1913         }
1914
1915         status = filename_convert(ctx,
1916                                 conn,
1917                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1918                                 fname,
1919                                 &smb_fname,
1920                                 NULL);
1921         if (!NT_STATUS_IS_OK(status)) {
1922                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1923                         reply_botherror(req,
1924                                         NT_STATUS_PATH_NOT_COVERED,
1925                                         ERRSRV, ERRbadpath);
1926                         goto out;
1927                 }
1928                 reply_nterror(req, status);
1929                 goto out;
1930         }
1931
1932         if (!map_open_params_to_ntcreate(
1933                     smb_fname->base_name, deny_mode, smb_ofun, &access_mask,
1934                     &share_mode, &create_disposition, &create_options)) {
1935                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1936                 goto out;
1937         }
1938
1939         status = SMB_VFS_CREATE_FILE(
1940                 conn,                                   /* conn */
1941                 req,                                    /* req */
1942                 0,                                      /* root_dir_fid */
1943                 smb_fname,                              /* fname */
1944                 access_mask,                            /* access_mask */
1945                 share_mode,                             /* share_access */
1946                 create_disposition,                     /* create_disposition*/
1947                 create_options,                         /* create_options */
1948                 smb_attr,                               /* file_attributes */
1949                 oplock_request,                         /* oplock_request */
1950                 0,                                      /* allocation_size */
1951                 NULL,                                   /* sd */
1952                 NULL,                                   /* ea_list */
1953                 &fsp,                                   /* result */
1954                 &smb_action);                           /* pinfo */
1955
1956         if (!NT_STATUS_IS_OK(status)) {
1957                 if (open_was_deferred(req->mid)) {
1958                         /* We have re-scheduled this call. */
1959                         goto out;
1960                 }
1961                 reply_openerror(req, status);
1962                 goto out;
1963         }
1964
1965         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1966            if the file is truncated or created. */
1967         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1968                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1969                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1970                         close_file(req, fsp, ERROR_CLOSE);
1971                         reply_nterror(req, NT_STATUS_DISK_FULL);
1972                         goto out;
1973                 }
1974                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1975                 if (retval < 0) {
1976                         close_file(req, fsp, ERROR_CLOSE);
1977                         reply_nterror(req, NT_STATUS_DISK_FULL);
1978                         goto out;
1979                 }
1980                 smb_fname->st.st_ex_size =
1981                     SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1982         }
1983
1984         fattr = dos_mode(conn, smb_fname);
1985         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1986         if (fattr & aDIR) {
1987                 close_file(req, fsp, ERROR_CLOSE);
1988                 reply_doserror(req, ERRDOS, ERRnoaccess);
1989                 goto out;
1990         }
1991
1992         /* If the caller set the extended oplock request bit
1993                 and we granted one (by whatever means) - set the
1994                 correct bit for extended oplock reply.
1995         */
1996
1997         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1998                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1999         }
2000
2001         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2002                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2003         }
2004
2005         /* If the caller set the core oplock request bit
2006                 and we granted one (by whatever means) - set the
2007                 correct bit for core oplock reply.
2008         */
2009
2010         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2011                 reply_outbuf(req, 19, 0);
2012         } else {
2013                 reply_outbuf(req, 15, 0);
2014         }
2015
2016         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2017                 SCVAL(req->outbuf, smb_flg,
2018                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2019         }
2020
2021         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2022                 SCVAL(req->outbuf, smb_flg,
2023                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2024         }
2025
2026         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2027         SSVAL(req->outbuf,smb_vwv3,fattr);
2028         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2029                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2030         } else {
2031                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2032         }
2033         SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2034         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2035         SSVAL(req->outbuf,smb_vwv11,smb_action);
2036
2037         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2038                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2039         }
2040
2041         chain_reply(req);
2042  out:
2043         TALLOC_FREE(smb_fname);
2044         END_PROFILE(SMBopenX);
2045         return;
2046 }
2047
2048 /****************************************************************************
2049  Reply to a SMBulogoffX.
2050 ****************************************************************************/
2051
2052 void reply_ulogoffX(struct smb_request *req)
2053 {
2054         struct smbd_server_connection *sconn = smbd_server_conn;
2055         user_struct *vuser;
2056
2057         START_PROFILE(SMBulogoffX);
2058
2059         vuser = get_valid_user_struct(sconn, req->vuid);
2060
2061         if(vuser == NULL) {
2062                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2063                          req->vuid));
2064         }
2065
2066         /* in user level security we are supposed to close any files
2067                 open by this user */
2068         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2069                 file_close_user(req->vuid);
2070         }
2071
2072         invalidate_vuid(sconn, req->vuid);
2073
2074         reply_outbuf(req, 2, 0);
2075
2076         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2077
2078         END_PROFILE(SMBulogoffX);
2079         chain_reply(req);
2080 }
2081
2082 /****************************************************************************
2083  Reply to a mknew or a create.
2084 ****************************************************************************/
2085
2086 void reply_mknew(struct smb_request *req)
2087 {
2088         connection_struct *conn = req->conn;
2089         struct smb_filename *smb_fname = NULL;
2090         char *fname = NULL;
2091         uint32 fattr = 0;
2092         struct smb_file_time ft;
2093         files_struct *fsp;
2094         int oplock_request = 0;
2095         NTSTATUS status;
2096         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2097         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2098         uint32 create_disposition;
2099         uint32 create_options = 0;
2100         TALLOC_CTX *ctx = talloc_tos();
2101
2102         START_PROFILE(SMBcreate);
2103         ZERO_STRUCT(ft);
2104
2105         if (req->wct < 3) {
2106                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107                 goto out;
2108         }
2109
2110         fattr = SVAL(req->vwv+0, 0);
2111         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2112
2113         /* mtime. */
2114         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2115
2116         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2117                             STR_TERMINATE, &status);
2118         if (!NT_STATUS_IS_OK(status)) {
2119                 reply_nterror(req, status);
2120                 goto out;
2121         }
2122
2123         status = filename_convert(ctx,
2124                                 conn,
2125                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2126                                 fname,
2127                                 &smb_fname,
2128                                 NULL);
2129         if (!NT_STATUS_IS_OK(status)) {
2130                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2131                         reply_botherror(req,
2132                                         NT_STATUS_PATH_NOT_COVERED,
2133                                         ERRSRV, ERRbadpath);
2134                         goto out;
2135                 }
2136                 reply_nterror(req, status);
2137                 goto out;
2138         }
2139
2140         if (fattr & aVOLID) {
2141                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2142                          "please report this\n",
2143                          smb_fname_str_dbg(smb_fname)));
2144         }
2145
2146         if(req->cmd == SMBmknew) {
2147                 /* We should fail if file exists. */
2148                 create_disposition = FILE_CREATE;
2149         } else {
2150                 /* Create if file doesn't exist, truncate if it does. */
2151                 create_disposition = FILE_OVERWRITE_IF;
2152         }
2153
2154         status = SMB_VFS_CREATE_FILE(
2155                 conn,                                   /* conn */
2156                 req,                                    /* req */
2157                 0,                                      /* root_dir_fid */
2158                 smb_fname,                              /* fname */
2159                 access_mask,                            /* access_mask */
2160                 share_mode,                             /* share_access */
2161                 create_disposition,                     /* create_disposition*/
2162                 create_options,                         /* create_options */
2163                 fattr,                                  /* file_attributes */
2164                 oplock_request,                         /* oplock_request */
2165                 0,                                      /* allocation_size */
2166                 NULL,                                   /* sd */
2167                 NULL,                                   /* ea_list */
2168                 &fsp,                                   /* result */
2169                 NULL);                                  /* pinfo */
2170
2171         if (!NT_STATUS_IS_OK(status)) {
2172                 if (open_was_deferred(req->mid)) {
2173                         /* We have re-scheduled this call. */
2174                         goto out;
2175                 }
2176                 reply_openerror(req, status);
2177                 goto out;
2178         }
2179
2180         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2181         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2182         if (!NT_STATUS_IS_OK(status)) {
2183                 END_PROFILE(SMBcreate);
2184                 goto out;
2185         }
2186
2187         reply_outbuf(req, 1, 0);
2188         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2189
2190         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2191                 SCVAL(req->outbuf,smb_flg,
2192                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2193         }
2194
2195         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2196                 SCVAL(req->outbuf,smb_flg,
2197                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2198         }
2199
2200         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2201         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2202                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2203                   (unsigned int)fattr));
2204
2205  out:
2206         TALLOC_FREE(smb_fname);
2207         END_PROFILE(SMBcreate);
2208         return;
2209 }
2210
2211 /****************************************************************************
2212  Reply to a create temporary file.
2213 ****************************************************************************/
2214
2215 void reply_ctemp(struct smb_request *req)
2216 {
2217         connection_struct *conn = req->conn;
2218         struct smb_filename *smb_fname = NULL;
2219         char *fname = NULL;
2220         uint32 fattr;
2221         files_struct *fsp;
2222         int oplock_request;
2223         int tmpfd;
2224         char *s;
2225         NTSTATUS status;
2226         TALLOC_CTX *ctx = talloc_tos();
2227
2228         START_PROFILE(SMBctemp);
2229
2230         if (req->wct < 3) {
2231                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2232                 goto out;
2233         }
2234
2235         fattr = SVAL(req->vwv+0, 0);
2236         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2237
2238         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2239                             STR_TERMINATE, &status);
2240         if (!NT_STATUS_IS_OK(status)) {
2241                 reply_nterror(req, status);
2242                 goto out;
2243         }
2244         if (*fname) {
2245                 fname = talloc_asprintf(ctx,
2246                                 "%s/TMXXXXXX",
2247                                 fname);
2248         } else {
2249                 fname = talloc_strdup(ctx, "TMXXXXXX");
2250         }
2251
2252         if (!fname) {
2253                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2254                 goto out;
2255         }
2256
2257         status = filename_convert(ctx, conn,
2258                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2259                                 fname,
2260                                 &smb_fname,
2261                                 NULL);
2262         if (!NT_STATUS_IS_OK(status)) {
2263                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2264                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2265                                         ERRSRV, ERRbadpath);
2266                         goto out;
2267                 }
2268                 reply_nterror(req, status);
2269                 goto out;
2270         }
2271
2272         tmpfd = mkstemp(smb_fname->base_name);
2273         if (tmpfd == -1) {
2274                 reply_nterror(req, map_nt_error_from_unix(errno));
2275                 goto out;
2276         }
2277
2278         SMB_VFS_STAT(conn, smb_fname);
2279
2280         /* We should fail if file does not exist. */
2281         status = SMB_VFS_CREATE_FILE(
2282                 conn,                                   /* conn */
2283                 req,                                    /* req */
2284                 0,                                      /* root_dir_fid */
2285                 smb_fname,                              /* fname */
2286                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2287                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2288                 FILE_OPEN,                              /* create_disposition*/
2289                 0,                                      /* create_options */
2290                 fattr,                                  /* file_attributes */
2291                 oplock_request,                         /* oplock_request */
2292                 0,                                      /* allocation_size */
2293                 NULL,                                   /* sd */
2294                 NULL,                                   /* ea_list */
2295                 &fsp,                                   /* result */
2296                 NULL);                                  /* pinfo */
2297
2298         /* close fd from mkstemp() */
2299         close(tmpfd);
2300
2301         if (!NT_STATUS_IS_OK(status)) {
2302                 if (open_was_deferred(req->mid)) {
2303                         /* We have re-scheduled this call. */
2304                         goto out;
2305                 }
2306                 reply_openerror(req, status);
2307                 goto out;
2308         }
2309
2310         reply_outbuf(req, 1, 0);
2311         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2312
2313         /* the returned filename is relative to the directory */
2314         s = strrchr_m(fsp->fsp_name, '/');
2315         if (!s) {
2316                 s = fsp->fsp_name;
2317         } else {
2318                 s++;
2319         }
2320
2321 #if 0
2322         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2323            thing in the byte section. JRA */
2324         SSVALS(p, 0, -1); /* what is this? not in spec */
2325 #endif
2326         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2327             == -1) {
2328                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2329                 goto out;
2330         }
2331
2332         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2333                 SCVAL(req->outbuf, smb_flg,
2334                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2335         }
2336
2337         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2338                 SCVAL(req->outbuf, smb_flg,
2339                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2340         }
2341
2342         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2343         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2344                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2345  out:
2346         TALLOC_FREE(smb_fname);
2347         END_PROFILE(SMBctemp);
2348         return;
2349 }
2350
2351 /*******************************************************************
2352  Check if a user is allowed to rename a file.
2353 ********************************************************************/
2354
2355 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2356                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2357 {
2358         struct smb_filename *smb_fname = NULL;
2359         NTSTATUS status;
2360         uint32 fmode;
2361
2362         if (!CAN_WRITE(conn)) {
2363                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2364         }
2365
2366         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
2367                                                   pst, &smb_fname);
2368         if (!NT_STATUS_IS_OK(status)) {
2369                 return status;
2370         }
2371
2372         fmode = dos_mode(conn, smb_fname);
2373         TALLOC_FREE(smb_fname);
2374         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2375                 return NT_STATUS_NO_SUCH_FILE;
2376         }
2377
2378         if (S_ISDIR(pst->st_ex_mode)) {
2379                 if (fsp->posix_open) {
2380                         return NT_STATUS_OK;
2381                 }
2382
2383                 /* If no pathnames are open below this
2384                    directory, allow the rename. */
2385
2386                 if (file_find_subpath(fsp)) {
2387                         return NT_STATUS_ACCESS_DENIED;
2388                 }
2389                 return NT_STATUS_OK;
2390         }
2391
2392         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2393                 return NT_STATUS_OK;
2394         }
2395
2396         return NT_STATUS_ACCESS_DENIED;
2397 }
2398
2399 /*******************************************************************
2400  * unlink a file with all relevant access checks
2401  *******************************************************************/
2402
2403 static NTSTATUS do_unlink(connection_struct *conn,
2404                         struct smb_request *req,
2405                         struct smb_filename *smb_fname,
2406                         uint32 dirtype)
2407 {
2408         uint32 fattr;
2409         files_struct *fsp;
2410         uint32 dirtype_orig = dirtype;
2411         NTSTATUS status;
2412
2413         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2414                   smb_fname_str_dbg(smb_fname),
2415                   dirtype));
2416
2417         if (!CAN_WRITE(conn)) {
2418                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2419         }
2420
2421         if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2422                 return map_nt_error_from_unix(errno);
2423         }
2424
2425         fattr = dos_mode(conn, smb_fname);
2426
2427         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2428                 dirtype = aDIR|aARCH|aRONLY;
2429         }
2430
2431         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2432         if (!dirtype) {
2433                 return NT_STATUS_NO_SUCH_FILE;
2434         }
2435
2436         if (!dir_check_ftype(conn, fattr, dirtype)) {
2437                 if (fattr & aDIR) {
2438                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2439                 }
2440                 return NT_STATUS_NO_SUCH_FILE;
2441         }
2442
2443         if (dirtype_orig & 0x8000) {
2444                 /* These will never be set for POSIX. */
2445                 return NT_STATUS_NO_SUCH_FILE;
2446         }
2447
2448 #if 0
2449         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2450                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2451         }
2452
2453         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2454                 return NT_STATUS_NO_SUCH_FILE;
2455         }
2456
2457         if (dirtype & 0xFF00) {
2458                 /* These will never be set for POSIX. */
2459                 return NT_STATUS_NO_SUCH_FILE;
2460         }
2461
2462         dirtype &= 0xFF;
2463         if (!dirtype) {
2464                 return NT_STATUS_NO_SUCH_FILE;
2465         }
2466
2467         /* Can't delete a directory. */
2468         if (fattr & aDIR) {
2469                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2470         }
2471 #endif
2472
2473 #if 0 /* JRATEST */
2474         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2475                 return NT_STATUS_OBJECT_NAME_INVALID;
2476 #endif /* JRATEST */
2477
2478         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2479
2480           On a Windows share, a file with read-only dosmode can be opened with
2481           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2482           fails with NT_STATUS_CANNOT_DELETE error.
2483
2484           This semantic causes a problem that a user can not
2485           rename a file with read-only dosmode on a Samba share
2486           from a Windows command prompt (i.e. cmd.exe, but can rename
2487           from Windows Explorer).
2488         */
2489
2490         if (!lp_delete_readonly(SNUM(conn))) {
2491                 if (fattr & aRONLY) {
2492                         return NT_STATUS_CANNOT_DELETE;
2493                 }
2494         }
2495
2496         /* On open checks the open itself will check the share mode, so
2497            don't do it here as we'll get it wrong. */
2498
2499         status = SMB_VFS_CREATE_FILE
2500                 (conn,                  /* conn */
2501                  req,                   /* req */
2502                  0,                     /* root_dir_fid */
2503                  smb_fname,             /* fname */
2504                  DELETE_ACCESS,         /* access_mask */
2505                  FILE_SHARE_NONE,       /* share_access */
2506                  FILE_OPEN,             /* create_disposition*/
2507                  FILE_NON_DIRECTORY_FILE, /* create_options */
2508                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2509                  0,                     /* oplock_request */
2510                  0,                     /* allocation_size */
2511                  NULL,                  /* sd */
2512                  NULL,                  /* ea_list */
2513                  &fsp,                  /* result */
2514                  NULL);                 /* pinfo */
2515
2516         if (!NT_STATUS_IS_OK(status)) {
2517                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2518                            nt_errstr(status)));
2519                 return status;
2520         }
2521
2522         /* The set is across all open files on this dev/inode pair. */
2523         if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2524                 close_file(req, fsp, NORMAL_CLOSE);
2525                 return NT_STATUS_ACCESS_DENIED;
2526         }
2527
2528         return close_file(req, fsp, NORMAL_CLOSE);
2529 }
2530
2531 /****************************************************************************
2532  The guts of the unlink command, split out so it may be called by the NT SMB
2533  code.
2534 ****************************************************************************/
2535
2536 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2537                           uint32 dirtype, const char *name_in, bool has_wild)
2538 {
2539         struct smb_filename *smb_fname = NULL;
2540         char *fname_dir = NULL;
2541         char *fname_mask = NULL;
2542         int count=0;
2543         NTSTATUS status = NT_STATUS_OK;
2544         TALLOC_CTX *ctx = talloc_tos();
2545
2546         status = unix_convert(ctx, conn, name_in, &smb_fname,
2547                               has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2548         if (!NT_STATUS_IS_OK(status)) {
2549                 goto out;
2550         }
2551
2552         /* Split up the directory from the filename/mask. */
2553         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2554                                       &fname_dir, &fname_mask);
2555         if (!NT_STATUS_IS_OK(status)) {
2556                 goto out;
2557         }
2558
2559         /*
2560          * We should only check the mangled cache
2561          * here if unix_convert failed. This means
2562          * that the path in 'mask' doesn't exist
2563          * on the file system and so we need to look
2564          * for a possible mangle. This patch from
2565          * Tine Smukavec <valentin.smukavec@hermes.si>.
2566          */
2567
2568         if (!VALID_STAT(smb_fname->st) &&
2569             mangle_is_mangled(fname_mask, conn->params)) {
2570                 char *new_mask = NULL;
2571                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2572                                             &new_mask, conn->params);
2573                 if (new_mask) {
2574                         TALLOC_FREE(fname_mask);
2575                         fname_mask = new_mask;
2576                 }
2577         }
2578
2579         if (!has_wild) {
2580
2581                 /*
2582                  * Only one file needs to be unlinked. Append the mask back
2583                  * onto the directory.
2584                  */
2585                 TALLOC_FREE(smb_fname->base_name);
2586                 smb_fname->base_name = talloc_asprintf(smb_fname,
2587                                                        "%s/%s",
2588                                                        fname_dir,
2589                                                        fname_mask);
2590                 if (!smb_fname->base_name) {
2591                         status = NT_STATUS_NO_MEMORY;
2592                         goto out;
2593                 }
2594                 if (dirtype == 0) {
2595                         dirtype = FILE_ATTRIBUTE_NORMAL;
2596                 }
2597
2598                 status = check_name(conn, smb_fname->base_name);
2599                 if (!NT_STATUS_IS_OK(status)) {
2600                         goto out;
2601                 }
2602
2603                 status = do_unlink(conn, req, smb_fname, dirtype);
2604                 if (!NT_STATUS_IS_OK(status)) {
2605                         goto out;
2606                 }
2607
2608                 count++;
2609         } else {
2610                 struct smb_Dir *dir_hnd = NULL;
2611                 long offset = 0;
2612                 const char *dname;
2613
2614                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2615                         status = NT_STATUS_OBJECT_NAME_INVALID;
2616                         goto out;
2617                 }
2618
2619                 if (strequal(fname_mask,"????????.???")) {
2620                         TALLOC_FREE(fname_mask);
2621                         fname_mask = talloc_strdup(ctx, "*");
2622                         if (!fname_mask) {
2623                                 status = NT_STATUS_NO_MEMORY;
2624                                 goto out;
2625                         }
2626                 }
2627
2628                 status = check_name(conn, fname_dir);
2629                 if (!NT_STATUS_IS_OK(status)) {
2630                         goto out;
2631                 }
2632
2633                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2634                                   dirtype);
2635                 if (dir_hnd == NULL) {
2636                         status = map_nt_error_from_unix(errno);
2637                         goto out;
2638                 }
2639
2640                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2641                    the pattern matches against the long name, otherwise the short name 
2642                    We don't implement this yet XXXX
2643                 */
2644
2645                 status = NT_STATUS_NO_SUCH_FILE;
2646
2647                 while ((dname = ReadDirName(dir_hnd, &offset,
2648                                             &smb_fname->st))) {
2649                         TALLOC_CTX *frame = talloc_stackframe();
2650
2651                         if (!is_visible_file(conn, fname_dir, dname,
2652                                              &smb_fname->st, true)) {
2653                                 TALLOC_FREE(frame);
2654                                 continue;
2655                         }
2656
2657                         /* Quick check for "." and ".." */
2658                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2659                                 TALLOC_FREE(frame);
2660                                 continue;
2661                         }
2662
2663                         if(!mask_match(dname, fname_mask,
2664                                        conn->case_sensitive)) {
2665                                 TALLOC_FREE(frame);
2666                                 continue;
2667                         }
2668
2669                         TALLOC_FREE(smb_fname->base_name);
2670                         smb_fname->base_name =
2671                             talloc_asprintf(smb_fname, "%s/%s",
2672                                             fname_dir, dname);
2673
2674                         if (!smb_fname->base_name) {
2675                                 TALLOC_FREE(dir_hnd);
2676                                 status = NT_STATUS_NO_MEMORY;
2677                                 TALLOC_FREE(frame);
2678                                 goto out;
2679                         }
2680
2681                         status = check_name(conn, smb_fname->base_name);
2682                         if (!NT_STATUS_IS_OK(status)) {
2683                                 TALLOC_FREE(dir_hnd);
2684                                 TALLOC_FREE(frame);
2685                                 goto out;
2686                         }
2687
2688                         status = do_unlink(conn, req, smb_fname, dirtype);
2689                         if (!NT_STATUS_IS_OK(status)) {
2690                                 TALLOC_FREE(frame);
2691                                 continue;
2692                         }
2693
2694                         count++;
2695                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2696                                  smb_fname->base_name));
2697
2698                         TALLOC_FREE(frame);
2699                 }
2700                 TALLOC_FREE(dir_hnd);
2701         }
2702
2703         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2704                 status = map_nt_error_from_unix(errno);
2705         }
2706
2707  out:
2708         TALLOC_FREE(smb_fname);
2709         TALLOC_FREE(fname_dir);
2710         TALLOC_FREE(fname_mask);
2711         return status;
2712 }
2713
2714 /****************************************************************************
2715  Reply to a unlink
2716 ****************************************************************************/
2717
2718 void reply_unlink(struct smb_request *req)
2719 {
2720         connection_struct *conn = req->conn;
2721         char *name = NULL;
2722         uint32 dirtype;
2723         NTSTATUS status;
2724         bool path_contains_wcard = False;
2725         TALLOC_CTX *ctx = talloc_tos();
2726
2727         START_PROFILE(SMBunlink);
2728
2729         if (req->wct < 1) {
2730                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2731                 END_PROFILE(SMBunlink);
2732                 return;
2733         }
2734
2735         dirtype = SVAL(req->vwv+0, 0);
2736
2737         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2738                                   STR_TERMINATE, &status,
2739                                   &path_contains_wcard);
2740         if (!NT_STATUS_IS_OK(status)) {
2741                 reply_nterror(req, status);
2742                 END_PROFILE(SMBunlink);
2743                 return;
2744         }
2745
2746         status = resolve_dfspath_wcard(ctx, conn,
2747                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2748                                        name,
2749                                        &name,
2750                                        &path_contains_wcard);
2751         if (!NT_STATUS_IS_OK(status)) {
2752                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2753                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2754                                         ERRSRV, ERRbadpath);
2755                         END_PROFILE(SMBunlink);
2756                         return;
2757                 }
2758                 reply_nterror(req, status);
2759                 END_PROFILE(SMBunlink);
2760                 return;
2761         }
2762
2763         DEBUG(3,("reply_unlink : %s\n",name));
2764
2765         status = unlink_internals(conn, req, dirtype, name,
2766                                   path_contains_wcard);
2767         if (!NT_STATUS_IS_OK(status)) {
2768                 if (open_was_deferred(req->mid)) {
2769                         /* We have re-scheduled this call. */
2770                         END_PROFILE(SMBunlink);
2771                         return;
2772                 }
2773                 reply_nterror(req, status);
2774                 END_PROFILE(SMBunlink);
2775                 return;
2776         }
2777
2778         reply_outbuf(req, 0, 0);
2779         END_PROFILE(SMBunlink);
2780
2781         return;
2782 }
2783
2784 /****************************************************************************
2785  Fail for readbraw.
2786 ****************************************************************************/
2787
2788 static void fail_readraw(void)
2789 {
2790         const char *errstr = talloc_asprintf(talloc_tos(),
2791                         "FAIL ! reply_readbraw: socket write fail (%s)",
2792                         strerror(errno));
2793         if (!errstr) {
2794                 errstr = "";
2795         }
2796         exit_server_cleanly(errstr);
2797 }
2798
2799 /****************************************************************************
2800  Fake (read/write) sendfile. Returns -1 on read or write fail.
2801 ****************************************************************************/
2802
2803 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2804                              size_t nread)
2805 {
2806         size_t bufsize;
2807         size_t tosend = nread;
2808         char *buf;
2809
2810         if (nread == 0) {
2811                 return 0;
2812         }
2813
2814         bufsize = MIN(nread, 65536);
2815
2816         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2817                 return -1;
2818         }
2819
2820         while (tosend > 0) {
2821                 ssize_t ret;
2822                 size_t cur_read;
2823
2824                 if (tosend > bufsize) {
2825                         cur_read = bufsize;
2826                 } else {
2827                         cur_read = tosend;
2828                 }
2829                 ret = read_file(fsp,buf,startpos,cur_read);
2830                 if (ret == -1) {
2831                         SAFE_FREE(buf);
2832                         return -1;
2833                 }
2834
2835                 /* If we had a short read, fill with zeros. */
2836                 if (ret < cur_read) {
2837                         memset(buf + ret, '\0', cur_read - ret);
2838                 }
2839
2840                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2841                         SAFE_FREE(buf);
2842                         return -1;
2843                 }
2844                 tosend -= cur_read;
2845                 startpos += cur_read;
2846         }
2847
2848         SAFE_FREE(buf);
2849         return (ssize_t)nread;
2850 }
2851
2852 #if defined(WITH_SENDFILE)
2853 /****************************************************************************
2854  Deal with the case of sendfile reading less bytes from the file than
2855  requested. Fill with zeros (all we can do).
2856 ****************************************************************************/
2857
2858 static void sendfile_short_send(files_struct *fsp,
2859                                 ssize_t nread,
2860                                 size_t headersize,
2861                                 size_t smb_maxcnt)
2862 {
2863 #define SHORT_SEND_BUFSIZE 1024
2864         if (nread < headersize) {
2865                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2866                         "header for file %s (%s). Terminating\n",
2867                         fsp->fsp_name, strerror(errno) ));
2868                 exit_server_cleanly("sendfile_short_send failed");
2869         }
2870
2871         nread -= headersize;
2872
2873         if (nread < smb_maxcnt) {
2874                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2875                 if (!buf) {
2876                         exit_server_cleanly("sendfile_short_send: "
2877                                 "malloc failed");
2878                 }
2879
2880                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2881                         "with zeros !\n", fsp->fsp_name));
2882
2883                 while (nread < smb_maxcnt) {
2884                         /*
2885                          * We asked for the real file size and told sendfile
2886                          * to not go beyond the end of the file. But it can
2887                          * happen that in between our fstat call and the
2888                          * sendfile call the file was truncated. This is very
2889                          * bad because we have already announced the larger
2890                          * number of bytes to the client.
2891                          *
2892                          * The best we can do now is to send 0-bytes, just as
2893                          * a read from a hole in a sparse file would do.
2894                          *
2895                          * This should happen rarely enough that I don't care
2896                          * about efficiency here :-)
2897                          */
2898                         size_t to_write;
2899
2900                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2901                         if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2902                                 exit_server_cleanly("sendfile_short_send: "
2903                                         "write_data failed");
2904                         }
2905                         nread += to_write;
2906                 }
2907                 SAFE_FREE(buf);
2908         }
2909 }
2910 #endif /* defined WITH_SENDFILE */
2911
2912 /****************************************************************************
2913  Return a readbraw error (4 bytes of zero).
2914 ****************************************************************************/
2915
2916 static void reply_readbraw_error(void)
2917 {
2918         char header[4];
2919         SIVAL(header,0,0);
2920         if (write_data(smbd_server_fd(),header,4) != 4) {
2921                 fail_readraw();
2922         }
2923 }
2924
2925 /****************************************************************************
2926  Use sendfile in readbraw.
2927 ****************************************************************************/
2928
2929 static void send_file_readbraw(connection_struct *conn,
2930                                struct smb_request *req,
2931                                files_struct *fsp,
2932                                SMB_OFF_T startpos,
2933                                size_t nread,
2934                                ssize_t mincount)
2935 {
2936         char *outbuf = NULL;
2937         ssize_t ret=0;
2938
2939 #if defined(WITH_SENDFILE)
2940         /*
2941          * We can only use sendfile on a non-chained packet 
2942          * but we can use on a non-oplocked file. tridge proved this
2943          * on a train in Germany :-). JRA.
2944          * reply_readbraw has already checked the length.
2945          */
2946
2947         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2948             (fsp->wcp == NULL) &&
2949             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2950                 ssize_t sendfile_read = -1;
2951                 char header[4];
2952                 DATA_BLOB header_blob;
2953
2954                 _smb_setlen(header,nread);
2955                 header_blob = data_blob_const(header, 4);
2956
2957                 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2958                                 &header_blob, startpos, nread)) == -1) {
2959                         /* Returning ENOSYS means no data at all was sent.
2960                          * Do this as a normal read. */
2961                         if (errno == ENOSYS) {
2962                                 goto normal_readbraw;
2963                         }
2964
2965                         /*
2966                          * Special hack for broken Linux with no working sendfile. If we
2967                          * return EINTR we sent the header but not the rest of the data.
2968                          * Fake this up by doing read/write calls.
2969                          */
2970                         if (errno == EINTR) {
2971                                 /* Ensure we don't do this again. */
2972                                 set_use_sendfile(SNUM(conn), False);
2973                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2974
2975                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2976                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2977                                                 fsp->fsp_name, strerror(errno) ));
2978                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2979                                 }
2980                                 return;
2981                         }
2982
2983                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2984                                 fsp->fsp_name, strerror(errno) ));
2985                         exit_server_cleanly("send_file_readbraw sendfile failed");
2986                 } else if (sendfile_read == 0) {
2987                         /*
2988                          * Some sendfile implementations return 0 to indicate
2989                          * that there was a short read, but nothing was
2990                          * actually written to the socket.  In this case,
2991                          * fallback to the normal read path so the header gets
2992                          * the correct byte count.
2993                          */
2994                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2995                                   "bytes falling back to the normal read: "
2996                                   "%s\n", fsp->fsp_name));
2997                         goto normal_readbraw;
2998                 }
2999
3000                 /* Deal with possible short send. */
3001                 if (sendfile_read != 4+nread) {
3002                         sendfile_short_send(fsp, sendfile_read, 4, nread);
3003                 }
3004                 return;
3005         }
3006
3007 normal_readbraw:
3008 #endif
3009
3010         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3011         if (!outbuf) {
3012                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3013                         (unsigned)(nread+4)));
3014                 reply_readbraw_error();
3015                 return;
3016         }
3017
3018         if (nread > 0) {
3019                 ret = read_file(fsp,outbuf+4,startpos,nread);
3020 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3021                 if (ret < mincount)
3022                         ret = 0;
3023 #else
3024                 if (ret < nread)
3025                         ret = 0;
3026 #endif
3027         }
3028
3029         _smb_setlen(outbuf,ret);
3030         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3031                 fail_readraw();
3032
3033         TALLOC_FREE(outbuf);
3034 }
3035
3036 /****************************************************************************
3037  Reply to a readbraw (core+ protocol).
3038 ****************************************************************************/
3039
3040 void reply_readbraw(struct smb_request *req)
3041 {
3042         connection_struct *conn = req->conn;
3043         ssize_t maxcount,mincount;
3044         size_t nread = 0;
3045         SMB_OFF_T startpos;
3046         files_struct *fsp;
3047         struct lock_struct lock;
3048         SMB_STRUCT_STAT st;
3049         SMB_OFF_T size = 0;
3050
3051         START_PROFILE(SMBreadbraw);
3052
3053         if (srv_is_signing_active(smbd_server_conn) ||
3054             is_encrypted_packet(req->inbuf)) {
3055                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3056                         "raw reads/writes are disallowed.");
3057         }
3058
3059         if (req->wct < 8) {
3060                 reply_readbraw_error();
3061                 END_PROFILE(SMBreadbraw);
3062                 return;
3063         }
3064
3065         /*
3066          * Special check if an oplock break has been issued
3067          * and the readraw request croses on the wire, we must
3068          * return a zero length response here.
3069          */
3070
3071         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3072
3073         /*
3074          * We have to do a check_fsp by hand here, as
3075          * we must always return 4 zero bytes on error,
3076          * not a NTSTATUS.
3077          */
3078
3079         if (!fsp || !conn || conn != fsp->conn ||
3080                         req->vuid != fsp->vuid ||
3081                         fsp->is_directory || fsp->fh->fd == -1) {
3082                 /*
3083                  * fsp could be NULL here so use the value from the packet. JRA.
3084                  */
3085                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3086                         "- cache prime?\n",
3087                         (int)SVAL(req->vwv+0, 0)));
3088                 reply_readbraw_error();
3089                 END_PROFILE(SMBreadbraw);
3090                 return;
3091         }
3092
3093         /* Do a "by hand" version of CHECK_READ. */
3094         if (!(fsp->can_read ||
3095                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3096                                 (fsp->access_mask & FILE_EXECUTE)))) {
3097                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3098                                 (int)SVAL(req->vwv+0, 0)));
3099                 reply_readbraw_error();
3100                 END_PROFILE(SMBreadbraw);
3101                 return;
3102         }
3103
3104         flush_write_cache(fsp, READRAW_FLUSH);
3105
3106         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3107         if(req->wct == 10) {
3108                 /*
3109                  * This is a large offset (64 bit) read.
3110                  */
3111 #ifdef LARGE_SMB_OFF_T
3112
3113                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3114
3115 #else /* !LARGE_SMB_OFF_T */
3116
3117                 /*
3118                  * Ensure we haven't been sent a >32 bit offset.
3119                  */
3120
3121                 if(IVAL(req->vwv+8, 0) != 0) {
3122                         DEBUG(0,("reply_readbraw: large offset "
3123                                 "(%x << 32) used and we don't support "
3124                                 "64 bit offsets.\n",
3125                         (unsigned int)IVAL(req->vwv+8, 0) ));
3126                         reply_readbraw_error();
3127                         END_PROFILE(SMBreadbraw);
3128                         return;
3129                 }
3130
3131 #endif /* LARGE_SMB_OFF_T */
3132
3133                 if(startpos < 0) {
3134                         DEBUG(0,("reply_readbraw: negative 64 bit "
3135                                 "readraw offset (%.0f) !\n",
3136                                 (double)startpos ));
3137                         reply_readbraw_error();
3138                         END_PROFILE(SMBreadbraw);
3139                         return;
3140                 }      
3141         }
3142
3143         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3144         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3145
3146         /* ensure we don't overrun the packet size */
3147         maxcount = MIN(65535,maxcount);
3148
3149         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3150             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3151             &lock);
3152
3153         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3154                 reply_readbraw_error();
3155                 END_PROFILE(SMBreadbraw);
3156                 return;
3157         }
3158
3159         if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3160                 size = st.st_ex_size;
3161         }
3162
3163         if (startpos >= size) {
3164                 nread = 0;
3165         } else {
3166                 nread = MIN(maxcount,(size - startpos));
3167         }
3168
3169 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3170         if (nread < mincount)
3171                 nread = 0;
3172 #endif
3173
3174         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3175                 "min=%lu nread=%lu\n",
3176                 fsp->fnum, (double)startpos,
3177                 (unsigned long)maxcount,
3178                 (unsigned long)mincount,
3179                 (unsigned long)nread ) );
3180
3181         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3182
3183         DEBUG(5,("reply_readbraw finished\n"));
3184
3185         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3186
3187         END_PROFILE(SMBreadbraw);
3188         return;
3189 }
3190
3191 #undef DBGC_CLASS
3192 #define DBGC_CLASS DBGC_LOCKING
3193
3194 /****************************************************************************
3195  Reply to a lockread (core+ protocol).
3196 ****************************************************************************/
3197
3198 void reply_lockread(struct smb_request *req)
3199 {
3200         connection_struct *conn = req->conn;
3201         ssize_t nread = -1;
3202         char *data;
3203         SMB_OFF_T startpos;
3204         size_t numtoread;
3205         NTSTATUS status;
3206         files_struct *fsp;
3207         struct byte_range_lock *br_lck = NULL;
3208         char *p = NULL;
3209         struct smbd_server_connection *sconn = smbd_server_conn;
3210
3211         START_PROFILE(SMBlockread);
3212
3213         if (req->wct < 5) {
3214                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3215                 END_PROFILE(SMBlockread);
3216                 return;
3217         }
3218
3219         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3220
3221         if (!check_fsp(conn, req, fsp)) {
3222                 END_PROFILE(SMBlockread);
3223                 return;
3224         }
3225
3226         if (!CHECK_READ(fsp,req)) {
3227                 reply_doserror(req, ERRDOS, ERRbadaccess);
3228                 END_PROFILE(SMBlockread);
3229                 return;
3230         }
3231
3232         numtoread = SVAL(req->vwv+1, 0);
3233         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3234
3235         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3236
3237         reply_outbuf(req, 5, numtoread + 3);
3238
3239         data = smb_buf(req->outbuf) + 3;
3240
3241         /*
3242          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3243          * protocol request that predates the read/write lock concept. 
3244          * Thus instead of asking for a read lock here we need to ask
3245          * for a write lock. JRA.
3246          * Note that the requested lock size is unaffected by max_recv.
3247          */
3248
3249         br_lck = do_lock(smbd_messaging_context(),
3250                         fsp,
3251                         req->smbpid,
3252                         (uint64_t)numtoread,
3253                         (uint64_t)startpos,
3254                         WRITE_LOCK,
3255                         WINDOWS_LOCK,
3256                         False, /* Non-blocking lock. */
3257                         &status,
3258                         NULL,
3259                         NULL);
3260         TALLOC_FREE(br_lck);
3261
3262         if (NT_STATUS_V(status)) {
3263                 reply_nterror(req, status);
3264                 END_PROFILE(SMBlockread);
3265                 return;
3266         }
3267
3268         /*
3269          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3270          */
3271
3272         if (numtoread > sconn->smb1.negprot.max_recv) {
3273                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3274 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3275                         (unsigned int)numtoread,
3276                         (unsigned int)sconn->smb1.negprot.max_recv));
3277                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3278         }
3279         nread = read_file(fsp,data,startpos,numtoread);
3280
3281         if (nread < 0) {
3282                 reply_nterror(req, map_nt_error_from_unix(errno));
3283                 END_PROFILE(SMBlockread);
3284                 return;
3285         }
3286
3287         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3288
3289         SSVAL(req->outbuf,smb_vwv0,nread);
3290         SSVAL(req->outbuf,smb_vwv5,nread+3);
3291         p = smb_buf(req->outbuf);
3292         SCVAL(p,0,0); /* pad byte. */
3293         SSVAL(p,1,nread);
3294
3295         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3296                  fsp->fnum, (int)numtoread, (int)nread));
3297
3298         END_PROFILE(SMBlockread);
3299         return;
3300 }
3301
3302 #undef DBGC_CLASS
3303 #define DBGC_CLASS DBGC_ALL
3304
3305 /****************************************************************************
3306  Reply to a read.
3307 ****************************************************************************/
3308
3309 void reply_read(struct smb_request *req)
3310 {
3311         connection_struct *conn = req->conn;
3312         size_t numtoread;
3313         ssize_t nread = 0;
3314         char *data;
3315         SMB_OFF_T startpos;
3316         int outsize = 0;
3317         files_struct *fsp;
3318         struct lock_struct lock;
3319         struct smbd_server_connection *sconn = smbd_server_conn;
3320
3321         START_PROFILE(SMBread);
3322
3323         if (req->wct < 3) {
3324                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3325                 END_PROFILE(SMBread);
3326                 return;
3327         }
3328
3329         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3330
3331         if (!check_fsp(conn, req, fsp)) {
3332                 END_PROFILE(SMBread);
3333                 return;
3334         }
3335
3336         if (!CHECK_READ(fsp,req)) {
3337                 reply_doserror(req, ERRDOS, ERRbadaccess);
3338                 END_PROFILE(SMBread);
3339                 return;
3340         }
3341
3342         numtoread = SVAL(req->vwv+1, 0);
3343         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3344
3345         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3346
3347         /*
3348          * The requested read size cannot be greater than max_recv. JRA.
3349          */
3350         if (numtoread > sconn->smb1.negprot.max_recv) {
3351                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3352 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3353                         (unsigned int)numtoread,
3354                         (unsigned int)sconn->smb1.negprot.max_recv));
3355                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3356         }
3357
3358         reply_outbuf(req, 5, numtoread+3);
3359
3360         data = smb_buf(req->outbuf) + 3;
3361
3362         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3363             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3364             &lock);
3365
3366         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3367                 reply_doserror(req, ERRDOS,ERRlock);
3368                 END_PROFILE(SMBread);
3369                 return;
3370         }
3371
3372         if (numtoread > 0)
3373                 nread = read_file(fsp,data,startpos,numtoread);
3374
3375         if (nread < 0) {
3376                 reply_nterror(req, map_nt_error_from_unix(errno));
3377                 goto strict_unlock;
3378         }
3379
3380         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3381
3382         SSVAL(req->outbuf,smb_vwv0,nread);
3383         SSVAL(req->outbuf,smb_vwv5,nread+3);
3384         SCVAL(smb_buf(req->outbuf),0,1);
3385         SSVAL(smb_buf(req->outbuf),1,nread);
3386
3387         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3388                 fsp->fnum, (int)numtoread, (int)nread ) );
3389
3390 strict_unlock:
3391         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3392
3393         END_PROFILE(SMBread);
3394         return;
3395 }
3396
3397 /****************************************************************************
3398  Setup readX header.
3399 ****************************************************************************/
3400
3401 static int setup_readX_header(struct smb_request *req, char *outbuf,
3402                               size_t smb_maxcnt)
3403 {
3404         int outsize;
3405         char *data;
3406
3407         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3408         data = smb_buf(outbuf);
3409
3410         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3411
3412         SCVAL(outbuf,smb_vwv0,0xFF);
3413         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3414         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3415         SSVAL(outbuf,smb_vwv6,
3416               req_wct_ofs(req)
3417               + 1               /* the wct field */
3418               + 12 * sizeof(uint16_t) /* vwv */
3419               + 2);             /* the buflen field */
3420         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3421         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3422         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3423         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3424         return outsize;
3425 }
3426
3427 /****************************************************************************
3428  Reply to a read and X - possibly using sendfile.
3429 ****************************************************************************/
3430
3431 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3432                             files_struct *fsp, SMB_OFF_T startpos,
3433                             size_t smb_maxcnt)
3434 {
3435         SMB_STRUCT_STAT sbuf;
3436         ssize_t nread = -1;
3437         struct lock_struct lock;
3438         int saved_errno = 0;
3439
3440         if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3441                 reply_nterror(req, map_nt_error_from_unix(errno));
3442                 return;
3443         }
3444
3445         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3446             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3447             &lock);
3448
3449         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3450                 reply_doserror(req, ERRDOS, ERRlock);
3451                 return;
3452         }
3453
3454         if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3455             || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3456                 /*
3457                  * We already know that we would do a short read, so don't
3458                  * try the sendfile() path.
3459                  */
3460                 goto nosendfile_read;
3461         }
3462
3463 #if defined(WITH_SENDFILE)
3464         /*
3465          * We can only use sendfile on a non-chained packet
3466          * but we can use on a non-oplocked file. tridge proved this
3467          * on a train in Germany :-). JRA.
3468          */
3469
3470         if (!req_is_in_chain(req) &&
3471             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3472             (fsp->wcp == NULL) &&
3473             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3474                 uint8 headerbuf[smb_size + 12 * 2];
3475                 DATA_BLOB header;
3476
3477                 /*
3478                  * Set up the packet header before send. We
3479                  * assume here the sendfile will work (get the
3480                  * correct amount of data).
3481                  */
3482
3483                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3484
3485                 construct_reply_common_req(req, (char *)headerbuf);
3486                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3487
3488                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3489                         /* Returning ENOSYS means no data at all was sent.
3490                            Do this as a normal read. */
3491                         if (errno == ENOSYS) {
3492                                 goto normal_read;
3493                         }
3494
3495                         /*
3496                          * Special hack for broken Linux with no working sendfile. If we
3497                          * return EINTR we sent the header but not the rest of the data.
3498                          * Fake this up by doing read/write calls.
3499                          */
3500
3501                         if (errno == EINTR) {
3502                                 /* Ensure we don't do this again. */
3503                                 set_use_sendfile(SNUM(conn), False);
3504                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3505                                 nread = fake_sendfile(fsp, startpos,
3506                                                       smb_maxcnt);
3507                                 if (nread == -1) {
3508                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3509                                                 fsp->fsp_name, strerror(errno) ));
3510                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3511                                 }
3512                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3513                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3514                                 /* No outbuf here means successful sendfile. */
3515                                 goto strict_unlock;
3516                         }
3517
3518                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3519                                 fsp->fsp_name, strerror(errno) ));
3520                         exit_server_cleanly("send_file_readX sendfile failed");
3521                 } else if (nread == 0) {
3522                         /*
3523                          * Some sendfile implementations return 0 to indicate
3524                          * that there was a short read, but nothing was
3525                          * actually written to the socket.  In this case,
3526                          * fallback to the normal read path so the header gets
3527                          * the correct byte count.
3528                          */
3529                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3530                                   "falling back to the normal read: %s\n",
3531                                   fsp->fsp_name));
3532                         goto normal_read;
3533                 }
3534
3535                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3536                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3537
3538                 /* Deal with possible short send. */
3539                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3540                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3541                 }
3542                 /* No outbuf here means successful sendfile. */
3543                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3544                 SMB_PERFCOUNT_END(&req->pcd);
3545                 goto strict_unlock;
3546         }
3547
3548 normal_read:
3549
3550 #endif
3551
3552         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3553                 uint8 headerbuf[smb_size + 2*12];
3554
3555                 construct_reply_common_req(req, (char *)headerbuf);
3556                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3557
3558                 /* Send out the header. */
3559                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3560                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3561                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3562                                 fsp->fsp_name, strerror(errno) ));
3563                         exit_server_cleanly("send_file_readX sendfile failed");
3564                 }
3565                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3566                 if (nread == -1) {
3567                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3568                                 fsp->fsp_name, strerror(errno) ));
3569                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3570                 }
3571                 goto strict_unlock;
3572         }
3573
3574 nosendfile_read:
3575
3576         reply_outbuf(req, 12, smb_maxcnt);
3577
3578         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3579         saved_errno = errno;
3580
3581         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3582
3583         if (nread < 0) {
3584                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3585                 return;
3586         }
3587
3588         setup_readX_header(req, (char *)req->outbuf, nread);
3589
3590         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3591                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3592
3593         chain_reply(req);
3594         return;
3595
3596  strict_unlock:
3597         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3598         TALLOC_FREE(req->outbuf);
3599         return;
3600 }
3601
3602 /****************************************************************************
3603  Reply to a read and X.
3604 ****************************************************************************/
3605
3606 void reply_read_and_X(struct smb_request *req)
3607 {
3608         connection_struct *conn = req->conn;
3609         files_struct *fsp;
3610         SMB_OFF_T startpos;
3611         size_t smb_maxcnt;
3612         bool big_readX = False;
3613 #if 0
3614         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3615 #endif
3616
3617         START_PROFILE(SMBreadX);
3618
3619         if ((req->wct != 10) && (req->wct != 12)) {
3620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3621                 return;
3622         }
3623
3624         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3625         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3626         smb_maxcnt = SVAL(req->vwv+5, 0);
3627
3628         /* If it's an IPC, pass off the pipe handler. */
3629         if (IS_IPC(conn)) {
3630                 reply_pipe_read_and_X(req);
3631                 END_PROFILE(SMBreadX);
3632                 return;
3633         }
3634
3635         if (!check_fsp(conn, req, fsp)) {
3636                 END_PROFILE(SMBreadX);
3637                 return;
3638         }
3639
3640         if (!CHECK_READ(fsp,req)) {
3641                 reply_doserror(req, ERRDOS,ERRbadaccess);
3642                 END_PROFILE(SMBreadX);
3643                 return;
3644         }
3645
3646         if (global_client_caps & CAP_LARGE_READX) {
3647                 size_t upper_size = SVAL(req->vwv+7, 0);
3648                 smb_maxcnt |= (upper_size<<16);
3649                 if (upper_size > 1) {
3650                         /* Can't do this on a chained packet. */
3651                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3652                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3653                                 END_PROFILE(SMBreadX);
3654                                 return;
3655                         }
3656                         /* We currently don't do this on signed or sealed data. */
3657                         if (srv_is_signing_active(smbd_server_conn) ||
3658                             is_encrypted_packet(req->inbuf)) {
3659                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3660                                 END_PROFILE(SMBreadX);
3661                                 return;
3662                         }
3663                         /* Is there room in the reply for this data ? */
3664                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3665                                 reply_nterror(req,
3666                                               NT_STATUS_INVALID_PARAMETER);
3667                                 END_PROFILE(SMBreadX);
3668                                 return;
3669                         }
3670                         big_readX = True;
3671                 }
3672         }
3673
3674         if (req->wct == 12) {
3675 #ifdef LARGE_SMB_OFF_T
3676                 /*
3677                  * This is a large offset (64 bit) read.
3678                  */
3679                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);