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