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