Fix spelling mistakes
[bbaumbach/samba-autobuild/.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 "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.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         if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
783                 exit_server_cleanly("reply_special: srv_send_smb failed.");
784         }
785
786         if (CVAL(outbuf, 0) != 0x82) {
787                 exit_server_cleanly("invalid netbios session");
788         }
789         return;
790 }
791
792 /****************************************************************************
793  Reply to a tcon.
794  conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
796
797 void reply_tcon(struct smb_request *req)
798 {
799         connection_struct *conn = req->conn;
800         const char *service;
801         char *service_buf = NULL;
802         char *password = NULL;
803         char *dev = NULL;
804         int pwlen=0;
805         NTSTATUS nt_status;
806         const uint8_t *p;
807         const char *p2;
808         TALLOC_CTX *ctx = talloc_tos();
809         struct smbXsrv_connection *xconn = req->xconn;
810         NTTIME now = timeval_to_nttime(&req->request_time);
811
812         START_PROFILE(SMBtcon);
813
814         if (req->buflen < 4) {
815                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
816                 END_PROFILE(SMBtcon);
817                 return;
818         }
819
820         p = req->buf + 1;
821         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
822         p += 1;
823         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
824         p += pwlen+1;
825         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
826         p += 1;
827
828         if (service_buf == NULL || password == NULL || dev == NULL) {
829                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830                 END_PROFILE(SMBtcon);
831                 return;
832         }
833         p2 = strrchr_m(service_buf,'\\');
834         if (p2) {
835                 service = p2+1;
836         } else {
837                 service = service_buf;
838         }
839
840         conn = make_connection(req, now, service, dev,
841                                req->vuid,&nt_status);
842         req->conn = conn;
843
844         if (!conn) {
845                 reply_nterror(req, nt_status);
846                 END_PROFILE(SMBtcon);
847                 return;
848         }
849
850         reply_outbuf(req, 2, 0);
851         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
852         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
853         SSVAL(req->outbuf,smb_tid,conn->cnum);
854
855         DEBUG(3,("tcon service=%s cnum=%d\n",
856                  service, conn->cnum));
857
858         END_PROFILE(SMBtcon);
859         return;
860 }
861
862 /****************************************************************************
863  Reply to a tcon and X.
864  conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
866
867 void reply_tcon_and_X(struct smb_request *req)
868 {
869         connection_struct *conn = req->conn;
870         const char *service = NULL;
871         TALLOC_CTX *ctx = talloc_tos();
872         /* what the client thinks the device is */
873         char *client_devicetype = NULL;
874         /* what the server tells the client the share represents */
875         const char *server_devicetype;
876         NTSTATUS nt_status;
877         int passlen;
878         char *path = NULL;
879         const uint8_t *p;
880         const char *q;
881         uint16_t tcon_flags;
882         struct smbXsrv_session *session = NULL;
883         NTTIME now = timeval_to_nttime(&req->request_time);
884         bool session_key_updated = false;
885         uint16_t optional_support = 0;
886         struct smbXsrv_connection *xconn = req->xconn;
887
888         START_PROFILE(SMBtconX);
889
890         if (req->wct < 4) {
891                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892                 END_PROFILE(SMBtconX);
893                 return;
894         }
895
896         passlen = SVAL(req->vwv+3, 0);
897         tcon_flags = SVAL(req->vwv+2, 0);
898
899         /* we might have to close an old one */
900         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
901                 struct smbXsrv_tcon *tcon;
902                 NTSTATUS status;
903
904                 tcon = conn->tcon;
905                 req->conn = NULL;
906                 conn = NULL;
907
908                 /*
909                  * TODO: cancel all outstanding requests on the tcon
910                  */
911                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
912                 if (!NT_STATUS_IS_OK(status)) {
913                         DEBUG(0, ("reply_tcon_and_X: "
914                                   "smbXsrv_tcon_disconnect() failed: %s\n",
915                                   nt_errstr(status)));
916                         /*
917                          * If we hit this case, there is something completely
918                          * wrong, so we better disconnect the transport connection.
919                          */
920                         END_PROFILE(SMBtconX);
921                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
922                         return;
923                 }
924
925                 TALLOC_FREE(tcon);
926                 /*
927                  * This tree id is gone. Make sure we can't re-use it
928                  * by accident.
929                  */
930                 req->tid = 0;
931         }
932
933         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
934                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
935                 END_PROFILE(SMBtconX);
936                 return;
937         }
938
939         if (xconn->smb1.negprot.encrypted_passwords) {
940                 p = req->buf + passlen;
941         } else {
942                 p = req->buf + passlen + 1;
943         }
944
945         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
946
947         if (path == NULL) {
948                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
949                 END_PROFILE(SMBtconX);
950                 return;
951         }
952
953         /*
954          * the service name can be either: \\server\share
955          * or share directly like on the DELL PowerVault 705
956          */
957         if (*path=='\\') {
958                 q = strchr_m(path+2,'\\');
959                 if (!q) {
960                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
961                         END_PROFILE(SMBtconX);
962                         return;
963                 }
964                 service = q+1;
965         } else {
966                 service = path;
967         }
968
969         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
970                                 &client_devicetype, p,
971                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
972
973         if (client_devicetype == NULL) {
974                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975                 END_PROFILE(SMBtconX);
976                 return;
977         }
978
979         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
980
981         nt_status = smb1srv_session_lookup(xconn,
982                                            req->vuid, now, &session);
983         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
984                 reply_force_doserror(req, ERRSRV, ERRbaduid);
985                 END_PROFILE(SMBtconX);
986                 return;
987         }
988         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
989                 reply_nterror(req, nt_status);
990                 END_PROFILE(SMBtconX);
991                 return;
992         }
993         if (!NT_STATUS_IS_OK(nt_status)) {
994                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
995                 END_PROFILE(SMBtconX);
996                 return;
997         }
998
999         if (session->global->auth_session_info == NULL) {
1000                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1001                 END_PROFILE(SMBtconX);
1002                 return;
1003         }
1004
1005         /*
1006          * If there is no application key defined yet
1007          * we create one.
1008          *
1009          * This means we setup the application key on the
1010          * first tcon that happens via the given session.
1011          *
1012          * Once the application key is defined, it does not
1013          * change any more.
1014          */
1015         if (session->global->application_key.length == 0 &&
1016             session->global->signing_key.length > 0)
1017         {
1018                 struct smbXsrv_session *x = session;
1019                 struct auth_session_info *session_info =
1020                         session->global->auth_session_info;
1021                 uint8_t session_key[16];
1022
1023                 ZERO_STRUCT(session_key);
1024                 memcpy(session_key, x->global->signing_key.data,
1025                        MIN(x->global->signing_key.length, sizeof(session_key)));
1026
1027                 /*
1028                  * The application key is truncated/padded to 16 bytes
1029                  */
1030                 x->global->application_key = data_blob_talloc(x->global,
1031                                                              session_key,
1032                                                              sizeof(session_key));
1033                 ZERO_STRUCT(session_key);
1034                 if (x->global->application_key.data == NULL) {
1035                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1036                         END_PROFILE(SMBtconX);
1037                         return;
1038                 }
1039
1040                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1041                         smb_key_derivation(x->global->application_key.data,
1042                                            x->global->application_key.length,
1043                                            x->global->application_key.data);
1044                         optional_support |= SMB_EXTENDED_SIGNATURES;
1045                 }
1046
1047                 /*
1048                  * Place the application key into the session_info
1049                  */
1050                 data_blob_clear_free(&session_info->session_key);
1051                 session_info->session_key = data_blob_dup_talloc(session_info,
1052                                                 x->global->application_key);
1053                 if (session_info->session_key.data == NULL) {
1054                         data_blob_clear_free(&x->global->application_key);
1055                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1056                         END_PROFILE(SMBtconX);
1057                         return;
1058                 }
1059                 session_key_updated = true;
1060         }
1061
1062         conn = make_connection(req, now, service, client_devicetype,
1063                                req->vuid, &nt_status);
1064         req->conn =conn;
1065
1066         if (!conn) {
1067                 if (session_key_updated) {
1068                         struct smbXsrv_session *x = session;
1069                         struct auth_session_info *session_info =
1070                                 session->global->auth_session_info;
1071                         data_blob_clear_free(&x->global->application_key);
1072                         data_blob_clear_free(&session_info->session_key);
1073                 }
1074                 reply_nterror(req, nt_status);
1075                 END_PROFILE(SMBtconX);
1076                 return;
1077         }
1078
1079         if ( IS_IPC(conn) )
1080                 server_devicetype = "IPC";
1081         else if ( IS_PRINT(conn) )
1082                 server_devicetype = "LPT1:";
1083         else
1084                 server_devicetype = "A:";
1085
1086         if (get_Protocol() < PROTOCOL_NT1) {
1087                 reply_outbuf(req, 2, 0);
1088                 if (message_push_string(&req->outbuf, server_devicetype,
1089                                         STR_TERMINATE|STR_ASCII) == -1) {
1090                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1091                         END_PROFILE(SMBtconX);
1092                         return;
1093                 }
1094         } else {
1095                 /* NT sets the fstype of IPC$ to the null string */
1096                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1097
1098                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1099                         /* Return permissions. */
1100                         uint32_t perm1 = 0;
1101                         uint32_t perm2 = 0;
1102
1103                         reply_outbuf(req, 7, 0);
1104
1105                         if (IS_IPC(conn)) {
1106                                 perm1 = FILE_ALL_ACCESS;
1107                                 perm2 = FILE_ALL_ACCESS;
1108                         } else {
1109                                 perm1 = conn->share_access;
1110                         }
1111
1112                         SIVAL(req->outbuf, smb_vwv3, perm1);
1113                         SIVAL(req->outbuf, smb_vwv5, perm2);
1114                 } else {
1115                         reply_outbuf(req, 3, 0);
1116                 }
1117
1118                 if ((message_push_string(&req->outbuf, server_devicetype,
1119                                          STR_TERMINATE|STR_ASCII) == -1)
1120                     || (message_push_string(&req->outbuf, fstype,
1121                                             STR_TERMINATE) == -1)) {
1122                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1123                         END_PROFILE(SMBtconX);
1124                         return;
1125                 }
1126
1127                 /* what does setting this bit do? It is set by NT4 and
1128                    may affect the ability to autorun mounted cdroms */
1129                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1130                 optional_support |=
1131                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1132
1133                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1134                         DEBUG(2,("Serving %s as a Dfs root\n",
1135                                  lp_servicename(ctx, SNUM(conn)) ));
1136                         optional_support |= SMB_SHARE_IN_DFS;
1137                 }
1138
1139                 SSVAL(req->outbuf, smb_vwv2, optional_support);
1140         }
1141
1142         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1143         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1144
1145         DEBUG(3,("tconX service=%s \n",
1146                  service));
1147
1148         /* set the incoming and outgoing tid to the just created one */
1149         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1150         SSVAL(req->outbuf,smb_tid,conn->cnum);
1151
1152         END_PROFILE(SMBtconX);
1153
1154         req->tid = conn->cnum;
1155 }
1156
1157 /****************************************************************************
1158  Reply to an unknown type.
1159 ****************************************************************************/
1160
1161 void reply_unknown_new(struct smb_request *req, uint8_t type)
1162 {
1163         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1164                   smb_fn_name(type), type, type));
1165         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1166         return;
1167 }
1168
1169 /****************************************************************************
1170  Reply to an ioctl.
1171  conn POINTER CAN BE NULL HERE !
1172 ****************************************************************************/
1173
1174 void reply_ioctl(struct smb_request *req)
1175 {
1176         connection_struct *conn = req->conn;
1177         uint16_t device;
1178         uint16_t function;
1179         uint32_t ioctl_code;
1180         int replysize;
1181         char *p;
1182
1183         START_PROFILE(SMBioctl);
1184
1185         if (req->wct < 3) {
1186                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1187                 END_PROFILE(SMBioctl);
1188                 return;
1189         }
1190
1191         device     = SVAL(req->vwv+1, 0);
1192         function   = SVAL(req->vwv+2, 0);
1193         ioctl_code = (device << 16) + function;
1194
1195         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1196
1197         switch (ioctl_code) {
1198             case IOCTL_QUERY_JOB_INFO:
1199                     replysize = 32;
1200                     break;
1201             default:
1202                     reply_force_doserror(req, ERRSRV, ERRnosupport);
1203                     END_PROFILE(SMBioctl);
1204                     return;
1205         }
1206
1207         reply_outbuf(req, 8, replysize+1);
1208         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1209         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1210         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
1211         p = smb_buf(req->outbuf);
1212         memset(p, '\0', replysize+1); /* valgrind-safe. */
1213         p += 1;          /* Allow for alignment */
1214
1215         switch (ioctl_code) {
1216                 case IOCTL_QUERY_JOB_INFO:                  
1217                 {
1218                         NTSTATUS status;
1219                         size_t len = 0;
1220                         files_struct *fsp = file_fsp(
1221                                 req, SVAL(req->vwv+0, 0));
1222                         if (!fsp) {
1223                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1224                                 END_PROFILE(SMBioctl);
1225                                 return;
1226                         }
1227                         /* Job number */
1228                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1229
1230                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1231                                     lp_netbios_name(), 15,
1232                                     STR_TERMINATE|STR_ASCII, &len);
1233                         if (!NT_STATUS_IS_OK(status)) {
1234                                 reply_nterror(req, status);
1235                                 END_PROFILE(SMBioctl);
1236                                 return;
1237                         }
1238                         if (conn) {
1239                                 status = srvstr_push((char *)req->outbuf, req->flags2,
1240                                             p+18,
1241                                             lp_servicename(talloc_tos(),
1242                                                            SNUM(conn)),
1243                                             13, STR_TERMINATE|STR_ASCII, &len);
1244                                 if (!NT_STATUS_IS_OK(status)) {
1245                                         reply_nterror(req, status);
1246                                         END_PROFILE(SMBioctl);
1247                                         return;
1248                                 }
1249                         } else {
1250                                 memset(p+18, 0, 13);
1251                         }
1252                         break;
1253                 }
1254         }
1255
1256         END_PROFILE(SMBioctl);
1257         return;
1258 }
1259
1260 /****************************************************************************
1261  Strange checkpath NTSTATUS mapping.
1262 ****************************************************************************/
1263
1264 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1265 {
1266         /* Strange DOS error code semantics only for checkpath... */
1267         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1268                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1269                         /* We need to map to ERRbadpath */
1270                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1271                 }
1272         }
1273         return status;
1274 }
1275
1276 /****************************************************************************
1277  Reply to a checkpath.
1278 ****************************************************************************/
1279
1280 void reply_checkpath(struct smb_request *req)
1281 {
1282         connection_struct *conn = req->conn;
1283         struct smb_filename *smb_fname = NULL;
1284         char *name = NULL;
1285         NTSTATUS status;
1286         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1287         TALLOC_CTX *ctx = talloc_tos();
1288
1289         START_PROFILE(SMBcheckpath);
1290
1291         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1292                             STR_TERMINATE, &status);
1293
1294         if (!NT_STATUS_IS_OK(status)) {
1295                 status = map_checkpath_error(req->flags2, status);
1296                 reply_nterror(req, status);
1297                 END_PROFILE(SMBcheckpath);
1298                 return;
1299         }
1300
1301         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1302
1303         status = filename_convert(ctx,
1304                                 conn,
1305                                 name,
1306                                 ucf_flags,
1307                                 NULL,
1308                                 NULL,
1309                                 &smb_fname);
1310
1311         if (!NT_STATUS_IS_OK(status)) {
1312                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1313                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1314                                         ERRSRV, ERRbadpath);
1315                         END_PROFILE(SMBcheckpath);
1316                         return;
1317                 }
1318                 goto path_err;
1319         }
1320
1321         if (!VALID_STAT(smb_fname->st) &&
1322             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1323                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1324                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1325                 status = map_nt_error_from_unix(errno);
1326                 goto path_err;
1327         }
1328
1329         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1330                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1331                                 ERRDOS, ERRbadpath);
1332                 goto out;
1333         }
1334
1335         reply_outbuf(req, 0, 0);
1336
1337  path_err:
1338         /* We special case this - as when a Windows machine
1339                 is parsing a path is steps through the components
1340                 one at a time - if a component fails it expects
1341                 ERRbadpath, not ERRbadfile.
1342         */
1343         status = map_checkpath_error(req->flags2, status);
1344         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1345                 /*
1346                  * Windows returns different error codes if
1347                  * the parent directory is valid but not the
1348                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1349                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1350                  * if the path is invalid.
1351                  */
1352                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1353                                 ERRDOS, ERRbadpath);
1354                 goto out;
1355         }
1356
1357         reply_nterror(req, status);
1358
1359  out:
1360         TALLOC_FREE(smb_fname);
1361         END_PROFILE(SMBcheckpath);
1362         return;
1363 }
1364
1365 /****************************************************************************
1366  Reply to a getatr.
1367 ****************************************************************************/
1368
1369 void reply_getatr(struct smb_request *req)
1370 {
1371         connection_struct *conn = req->conn;
1372         struct smb_filename *smb_fname = NULL;
1373         char *fname = NULL;
1374         int mode=0;
1375         off_t size=0;
1376         time_t mtime=0;
1377         const char *p;
1378         NTSTATUS status;
1379         TALLOC_CTX *ctx = talloc_tos();
1380         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1381
1382         START_PROFILE(SMBgetatr);
1383
1384         p = (const char *)req->buf + 1;
1385         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1386         if (!NT_STATUS_IS_OK(status)) {
1387                 reply_nterror(req, status);
1388                 goto out;
1389         }
1390
1391         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1392                 under WfWg - weird! */
1393         if (*fname == '\0') {
1394                 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1395                 if (!CAN_WRITE(conn)) {
1396                         mode |= FILE_ATTRIBUTE_READONLY;
1397                 }
1398                 size = 0;
1399                 mtime = 0;
1400         } else {
1401                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1402                 status = filename_convert(ctx,
1403                                 conn,
1404                                 fname,
1405                                 ucf_flags,
1406                                 NULL,
1407                                 NULL,
1408                                 &smb_fname);
1409                 if (!NT_STATUS_IS_OK(status)) {
1410                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1411                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1412                                                 ERRSRV, ERRbadpath);
1413                                 goto out;
1414                         }
1415                         reply_nterror(req, status);
1416                         goto out;
1417                 }
1418                 if (!VALID_STAT(smb_fname->st) &&
1419                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1420                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1421                                  smb_fname_str_dbg(smb_fname),
1422                                  strerror(errno)));
1423                         reply_nterror(req,  map_nt_error_from_unix(errno));
1424                         goto out;
1425                 }
1426
1427                 mode = dos_mode(conn, smb_fname);
1428                 size = smb_fname->st.st_ex_size;
1429
1430                 if (ask_sharemode) {
1431                         struct timespec write_time_ts;
1432                         struct file_id fileid;
1433
1434                         ZERO_STRUCT(write_time_ts);
1435                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1436                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1437                         if (!null_timespec(write_time_ts)) {
1438                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1439                         }
1440                 }
1441
1442                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1443                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1444                         size = 0;
1445                 }
1446         }
1447
1448         reply_outbuf(req, 10, 0);
1449
1450         SSVAL(req->outbuf,smb_vwv0,mode);
1451         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1452                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1453         } else {
1454                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1455         }
1456         SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1457
1458         if (get_Protocol() >= PROTOCOL_NT1) {
1459                 SSVAL(req->outbuf, smb_flg2,
1460                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1461         }
1462
1463         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1464                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1465
1466  out:
1467         TALLOC_FREE(smb_fname);
1468         TALLOC_FREE(fname);
1469         END_PROFILE(SMBgetatr);
1470         return;
1471 }
1472
1473 /****************************************************************************
1474  Reply to a setatr.
1475 ****************************************************************************/
1476
1477 void reply_setatr(struct smb_request *req)
1478 {
1479         struct smb_file_time ft;
1480         connection_struct *conn = req->conn;
1481         struct smb_filename *smb_fname = NULL;
1482         char *fname = NULL;
1483         int mode;
1484         time_t mtime;
1485         const char *p;
1486         NTSTATUS status;
1487         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1488         TALLOC_CTX *ctx = talloc_tos();
1489
1490         START_PROFILE(SMBsetatr);
1491
1492         ZERO_STRUCT(ft);
1493
1494         if (req->wct < 2) {
1495                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1496                 goto out;
1497         }
1498
1499         p = (const char *)req->buf + 1;
1500         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1501         if (!NT_STATUS_IS_OK(status)) {
1502                 reply_nterror(req, status);
1503                 goto out;
1504         }
1505
1506         status = filename_convert(ctx,
1507                                 conn,
1508                                 fname,
1509                                 ucf_flags,
1510                                 NULL,
1511                                 NULL,
1512                                 &smb_fname);
1513         if (!NT_STATUS_IS_OK(status)) {
1514                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1515                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1516                                         ERRSRV, ERRbadpath);
1517                         goto out;
1518                 }
1519                 reply_nterror(req, status);
1520                 goto out;
1521         }
1522
1523         if (smb_fname->base_name[0] == '.' &&
1524             smb_fname->base_name[1] == '\0') {
1525                 /*
1526                  * Not sure here is the right place to catch this
1527                  * condition. Might be moved to somewhere else later -- vl
1528                  */
1529                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1530                 goto out;
1531         }
1532
1533         mode = SVAL(req->vwv+0, 0);
1534         mtime = srv_make_unix_date3(req->vwv+1);
1535
1536         if (mode != FILE_ATTRIBUTE_NORMAL) {
1537                 if (VALID_STAT_OF_DIR(smb_fname->st))
1538                         mode |= FILE_ATTRIBUTE_DIRECTORY;
1539                 else
1540                         mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1541
1542                 status = check_access(conn, NULL, smb_fname,
1543                                         FILE_WRITE_ATTRIBUTES);
1544                 if (!NT_STATUS_IS_OK(status)) {
1545                         reply_nterror(req, status);
1546                         goto out;
1547                 }
1548
1549                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1550                                      false) != 0) {
1551                         reply_nterror(req, map_nt_error_from_unix(errno));
1552                         goto out;
1553                 }
1554         }
1555
1556         ft.mtime = convert_time_t_to_timespec(mtime);
1557         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1558         if (!NT_STATUS_IS_OK(status)) {
1559                 reply_nterror(req, status);
1560                 goto out;
1561         }
1562
1563         reply_outbuf(req, 0, 0);
1564
1565         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1566                  mode));
1567  out:
1568         TALLOC_FREE(smb_fname);
1569         END_PROFILE(SMBsetatr);
1570         return;
1571 }
1572
1573 /****************************************************************************
1574  Reply to a dskattr.
1575 ****************************************************************************/
1576
1577 void reply_dskattr(struct smb_request *req)
1578 {
1579         connection_struct *conn = req->conn;
1580         uint64_t ret;
1581         uint64_t dfree,dsize,bsize;
1582         struct smb_filename smb_fname;
1583         START_PROFILE(SMBdskattr);
1584
1585         ZERO_STRUCT(smb_fname);
1586         smb_fname.base_name = discard_const_p(char, ".");
1587
1588         if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1589                 reply_nterror(req, map_nt_error_from_unix(errno));
1590                 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1591                 END_PROFILE(SMBdskattr);
1592                 return;
1593         }
1594
1595         ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1596         if (ret == (uint64_t)-1) {
1597                 reply_nterror(req, map_nt_error_from_unix(errno));
1598                 END_PROFILE(SMBdskattr);
1599                 return;
1600         }
1601
1602         /*
1603          * Force max to fit in 16 bit fields.
1604          */
1605         while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1606                 dfree /= 2;
1607                 dsize /= 2;
1608                 bsize *= 2;
1609                 if (bsize > (WORDMAX*512)) {
1610                         bsize = (WORDMAX*512);
1611                         if (dsize > WORDMAX)
1612                                 dsize = WORDMAX;
1613                         if (dfree >  WORDMAX)
1614                                 dfree = WORDMAX;
1615                         break;
1616                 }
1617         }
1618
1619         reply_outbuf(req, 5, 0);
1620
1621         if (get_Protocol() <= PROTOCOL_LANMAN2) {
1622                 double total_space, free_space;
1623                 /* we need to scale this to a number that DOS6 can handle. We
1624                    use floating point so we can handle large drives on systems
1625                    that don't have 64 bit integers 
1626
1627                    we end up displaying a maximum of 2G to DOS systems
1628                 */
1629                 total_space = dsize * (double)bsize;
1630                 free_space = dfree * (double)bsize;
1631
1632                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1633                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1634
1635                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1636                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1637
1638                 SSVAL(req->outbuf,smb_vwv0,dsize);
1639                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1640                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1641                 SSVAL(req->outbuf,smb_vwv3,dfree);
1642         } else {
1643                 SSVAL(req->outbuf,smb_vwv0,dsize);
1644                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1645                 SSVAL(req->outbuf,smb_vwv2,512);
1646                 SSVAL(req->outbuf,smb_vwv3,dfree);
1647         }
1648
1649         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1650
1651         END_PROFILE(SMBdskattr);
1652         return;
1653 }
1654
1655 /*
1656  * Utility function to split the filename from the directory.
1657  */
1658 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1659                                      char **fname_dir_out,
1660                                      char **fname_mask_out)
1661 {
1662         const char *p = NULL;
1663         char *fname_dir = NULL;
1664         char *fname_mask = NULL;
1665
1666         p = strrchr_m(fname_in, '/');
1667         if (!p) {
1668                 fname_dir = talloc_strdup(ctx, ".");
1669                 fname_mask = talloc_strdup(ctx, fname_in);
1670         } else {
1671                 fname_dir = talloc_strndup(ctx, fname_in,
1672                     PTR_DIFF(p, fname_in));
1673                 fname_mask = talloc_strdup(ctx, p+1);
1674         }
1675
1676         if (!fname_dir || !fname_mask) {
1677                 TALLOC_FREE(fname_dir);
1678                 TALLOC_FREE(fname_mask);
1679                 return NT_STATUS_NO_MEMORY;
1680         }
1681
1682         *fname_dir_out = fname_dir;
1683         *fname_mask_out = fname_mask;
1684         return NT_STATUS_OK;
1685 }
1686
1687 /****************************************************************************
1688  Make a dir struct.
1689 ****************************************************************************/
1690
1691 static bool make_dir_struct(TALLOC_CTX *ctx,
1692                             char *buf,
1693                             const char *mask,
1694                             const char *fname,
1695                             off_t size,
1696                             uint32_t mode,
1697                             time_t date,
1698                             bool uc)
1699 {
1700         char *p;
1701         char *mask2 = talloc_strdup(ctx, mask);
1702
1703         if (!mask2) {
1704                 return False;
1705         }
1706
1707         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1708                 size = 0;
1709         }
1710
1711         memset(buf+1,' ',11);
1712         if ((p = strchr_m(mask2,'.')) != NULL) {
1713                 *p = 0;
1714                 push_ascii(buf+1,mask2,8, 0);
1715                 push_ascii(buf+9,p+1,3, 0);
1716                 *p = '.';
1717         } else {
1718                 push_ascii(buf+1,mask2,11, 0);
1719         }
1720
1721         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1722         SCVAL(buf,21,mode);
1723         srv_put_dos_date(buf,22,date);
1724         SSVAL(buf,26,size & 0xFFFF);
1725         SSVAL(buf,28,(size >> 16)&0xFFFF);
1726         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1727            Strange, but verified on W2K3. Needed for OS/2. JRA. */
1728         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1729         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1730         return True;
1731 }
1732
1733 /****************************************************************************
1734  Reply to a search.
1735  Can be called from SMBsearch, SMBffirst or SMBfunique.
1736 ****************************************************************************/
1737
1738 void reply_search(struct smb_request *req)
1739 {
1740         connection_struct *conn = req->conn;
1741         char *path = NULL;
1742         char *mask = NULL;
1743         char *directory = NULL;
1744         struct smb_filename *smb_fname = NULL;
1745         char *fname = NULL;
1746         off_t size;
1747         uint32_t mode;
1748         struct timespec date;
1749         uint32_t dirtype;
1750         unsigned int numentries = 0;
1751         unsigned int maxentries = 0;
1752         bool finished = False;
1753         const char *p;
1754         int status_len;
1755         char status[21];
1756         int dptr_num= -1;
1757         bool check_descend = False;
1758         bool expect_close = False;
1759         NTSTATUS nt_status;
1760         bool mask_contains_wcard = False;
1761         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1762         TALLOC_CTX *ctx = talloc_tos();
1763         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1764         struct dptr_struct *dirptr = NULL;
1765         struct smbXsrv_connection *xconn = req->xconn;
1766         struct smbd_server_connection *sconn = req->sconn;
1767
1768         START_PROFILE(SMBsearch);
1769
1770         if (req->wct < 2) {
1771                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1772                 goto out;
1773         }
1774
1775         if (req->posix_pathnames) {
1776                 reply_unknown_new(req, req->cmd);
1777                 goto out;
1778         }
1779
1780         /* If we were called as SMBffirst then we must expect close. */
1781         if(req->cmd == SMBffirst) {
1782                 expect_close = True;
1783         }
1784
1785         reply_outbuf(req, 1, 3);
1786         maxentries = SVAL(req->vwv+0, 0);
1787         dirtype = SVAL(req->vwv+1, 0);
1788         p = (const char *)req->buf + 1;
1789         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1790                                        &nt_status, &mask_contains_wcard);
1791         if (!NT_STATUS_IS_OK(nt_status)) {
1792                 reply_nterror(req, nt_status);
1793                 goto out;
1794         }
1795
1796         p++;
1797         status_len = SVAL(p, 0);
1798         p += 2;
1799
1800         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1801
1802         if (status_len == 0) {
1803                 struct smb_filename *smb_dname = NULL;
1804                 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1805                         ucf_flags_from_smb_request(req);
1806                 nt_status = filename_convert(ctx, conn,
1807                                              path,
1808                                              ucf_flags,
1809                                              NULL,
1810                                              &mask_contains_wcard,
1811                                              &smb_fname);
1812                 if (!NT_STATUS_IS_OK(nt_status)) {
1813                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1814                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1815                                                 ERRSRV, ERRbadpath);
1816                                 goto out;
1817                         }
1818                         reply_nterror(req, nt_status);
1819                         goto out;
1820                 }
1821
1822                 directory = smb_fname->base_name;
1823
1824                 p = strrchr_m(directory,'/');
1825                 if ((p != NULL) && (*directory != '/')) {
1826                         mask = talloc_strdup(ctx, p + 1);
1827                         directory = talloc_strndup(ctx, directory,
1828                                                    PTR_DIFF(p, directory));
1829                 } else {
1830                         mask = talloc_strdup(ctx, directory);
1831                         directory = talloc_strdup(ctx,".");
1832                 }
1833
1834                 if (!directory) {
1835                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1836                         goto out;
1837                 }
1838
1839                 memset((char *)status,'\0',21);
1840                 SCVAL(status,0,(dirtype & 0x1F));
1841
1842                 smb_dname = synthetic_smb_fname(talloc_tos(),
1843                                         directory,
1844                                         NULL,
1845                                         NULL,
1846                                         smb_fname->flags);
1847                 if (smb_dname == NULL) {
1848                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1849                         goto out;
1850                 }
1851
1852                 nt_status = dptr_create(conn,
1853                                         NULL, /* req */
1854                                         NULL, /* fsp */
1855                                         smb_dname,
1856                                         True,
1857                                         expect_close,
1858                                         req->smbpid,
1859                                         mask,
1860                                         mask_contains_wcard,
1861                                         dirtype,
1862                                         &dirptr);
1863
1864                 TALLOC_FREE(smb_dname);
1865
1866                 if (!NT_STATUS_IS_OK(nt_status)) {
1867                         reply_nterror(req, nt_status);
1868                         goto out;
1869                 }
1870                 dptr_num = dptr_dnum(dirptr);
1871         } else {
1872                 int status_dirtype;
1873                 const char *dirpath;
1874
1875                 memcpy(status,p,21);
1876                 status_dirtype = CVAL(status,0) & 0x1F;
1877                 if (status_dirtype != (dirtype & 0x1F)) {
1878                         dirtype = status_dirtype;
1879                 }
1880
1881                 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1882                 if (!dirptr) {
1883                         goto SearchEmpty;
1884                 }
1885                 dirpath = dptr_path(sconn, dptr_num);
1886                 directory = talloc_strdup(ctx, dirpath);
1887                 if (!directory) {
1888                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1889                         goto out;
1890                 }
1891
1892                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1893                 if (!mask) {
1894                         goto SearchEmpty;
1895                 }
1896                 /*
1897                  * For a 'continue' search we have no string. So
1898                  * check from the initial saved string.
1899                  */
1900                 if (!req->posix_pathnames) {
1901                         mask_contains_wcard = ms_has_wild(mask);
1902                 }
1903                 dirtype = dptr_attr(sconn, dptr_num);
1904         }
1905
1906         DEBUG(4,("dptr_num is %d\n",dptr_num));
1907
1908         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1909                 char buf[DIR_STRUCT_SIZE];
1910                 memcpy(buf,status,21);
1911                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1912                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1913                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1914                         goto out;
1915                 }
1916                 dptr_fill(sconn, buf+12,dptr_num);
1917                 if (dptr_zero(buf+12) && (status_len==0)) {
1918                         numentries = 1;
1919                 } else {
1920                         numentries = 0;
1921                 }
1922                 if (message_push_blob(&req->outbuf,
1923                                       data_blob_const(buf, sizeof(buf)))
1924                     == -1) {
1925                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1926                         goto out;
1927                 }
1928         } else {
1929                 unsigned int i;
1930                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1931                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1932
1933                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1934
1935                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1936                          directory,lp_dont_descend(ctx, SNUM(conn))));
1937                 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1938                         check_descend = True;
1939                 }
1940
1941                 for (i=numentries;(i<maxentries) && !finished;i++) {
1942                         finished = !get_dir_entry(ctx,
1943                                                   dirptr,
1944                                                   mask,
1945                                                   dirtype,
1946                                                   &fname,
1947                                                   &size,
1948                                                   &mode,
1949                                                   &date,
1950                                                   check_descend,
1951                                                   ask_sharemode);
1952                         if (!finished) {
1953                                 char buf[DIR_STRUCT_SIZE];
1954                                 memcpy(buf,status,21);
1955                                 if (!make_dir_struct(ctx,
1956                                                 buf,
1957                                                 mask,
1958                                                 fname,
1959                                                 size,
1960                                                 mode,
1961                                                 convert_timespec_to_time_t(date),
1962                                                 !allow_long_path_components)) {
1963                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1964                                         goto out;
1965                                 }
1966                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1967                                         break;
1968                                 }
1969                                 if (message_push_blob(&req->outbuf,
1970                                                       data_blob_const(buf, sizeof(buf)))
1971                                     == -1) {
1972                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1973                                         goto out;
1974                                 }
1975                                 numentries++;
1976                         }
1977                 }
1978         }
1979
1980   SearchEmpty:
1981
1982         /* If we were called as SMBffirst with smb_search_id == NULL
1983                 and no entries were found then return error and close dirptr 
1984                 (X/Open spec) */
1985
1986         if (numentries == 0) {
1987                 dptr_close(sconn, &dptr_num);
1988         } else if(expect_close && status_len == 0) {
1989                 /* Close the dptr - we know it's gone */
1990                 dptr_close(sconn, &dptr_num);
1991         }
1992
1993         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1994         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1995                 dptr_close(sconn, &dptr_num);
1996         }
1997
1998         if ((numentries == 0) && !mask_contains_wcard) {
1999                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2000                 goto out;
2001         }
2002
2003         SSVAL(req->outbuf,smb_vwv0,numentries);
2004         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2005         SCVAL(smb_buf(req->outbuf),0,5);
2006         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2007
2008         /* The replies here are never long name. */
2009         SSVAL(req->outbuf, smb_flg2,
2010               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2011         if (!allow_long_path_components) {
2012                 SSVAL(req->outbuf, smb_flg2,
2013                       SVAL(req->outbuf, smb_flg2)
2014                       & (~FLAGS2_LONG_PATH_COMPONENTS));
2015         }
2016
2017         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2018         SSVAL(req->outbuf, smb_flg2,
2019               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2020
2021         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2022                 smb_fn_name(req->cmd),
2023                 mask,
2024                 directory,
2025                 dirtype,
2026                 numentries,
2027                 maxentries ));
2028  out:
2029         TALLOC_FREE(directory);
2030         TALLOC_FREE(mask);
2031         TALLOC_FREE(smb_fname);
2032         END_PROFILE(SMBsearch);
2033         return;
2034 }
2035
2036 /****************************************************************************
2037  Reply to a fclose (stop directory search).
2038 ****************************************************************************/
2039
2040 void reply_fclose(struct smb_request *req)
2041 {
2042         int status_len;
2043         char status[21];
2044         int dptr_num= -2;
2045         const char *p;
2046         char *path = NULL;
2047         NTSTATUS err;
2048         bool path_contains_wcard = False;
2049         TALLOC_CTX *ctx = talloc_tos();
2050         struct smbd_server_connection *sconn = req->sconn;
2051
2052         START_PROFILE(SMBfclose);
2053
2054         if (req->posix_pathnames) {
2055                 reply_unknown_new(req, req->cmd);
2056                 END_PROFILE(SMBfclose);
2057                 return;
2058         }
2059
2060         p = (const char *)req->buf + 1;
2061         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2062                                        &err, &path_contains_wcard);
2063         if (!NT_STATUS_IS_OK(err)) {
2064                 reply_nterror(req, err);
2065                 END_PROFILE(SMBfclose);
2066                 return;
2067         }
2068         p++;
2069         status_len = SVAL(p,0);
2070         p += 2;
2071
2072         if (status_len == 0) {
2073                 reply_force_doserror(req, ERRSRV, ERRsrverror);
2074                 END_PROFILE(SMBfclose);
2075                 return;
2076         }
2077
2078         memcpy(status,p,21);
2079
2080         if(dptr_fetch(sconn, status+12,&dptr_num)) {
2081                 /*  Close the dptr - we know it's gone */
2082                 dptr_close(sconn, &dptr_num);
2083         }
2084
2085         reply_outbuf(req, 1, 0);
2086         SSVAL(req->outbuf,smb_vwv0,0);
2087
2088         DEBUG(3,("search close\n"));
2089
2090         END_PROFILE(SMBfclose);
2091         return;
2092 }
2093
2094 /****************************************************************************
2095  Reply to an open.
2096 ****************************************************************************/
2097
2098 void reply_open(struct smb_request *req)
2099 {
2100         connection_struct *conn = req->conn;
2101         struct smb_filename *smb_fname = NULL;
2102         char *fname = NULL;
2103         uint32_t fattr=0;
2104         off_t size = 0;
2105         time_t mtime=0;
2106         int info;
2107         files_struct *fsp;
2108         int oplock_request;
2109         int deny_mode;
2110         uint32_t dos_attr;
2111         uint32_t access_mask;
2112         uint32_t share_mode;
2113         uint32_t create_disposition;
2114         uint32_t create_options = 0;
2115         uint32_t private_flags = 0;
2116         NTSTATUS status;
2117         uint32_t ucf_flags;
2118         TALLOC_CTX *ctx = talloc_tos();
2119
2120         START_PROFILE(SMBopen);
2121
2122         if (req->wct < 2) {
2123                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2124                 goto out;
2125         }
2126
2127         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2128         deny_mode = SVAL(req->vwv+0, 0);
2129         dos_attr = SVAL(req->vwv+1, 0);
2130
2131         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2132                             STR_TERMINATE, &status);
2133         if (!NT_STATUS_IS_OK(status)) {
2134                 reply_nterror(req, status);
2135                 goto out;
2136         }
2137
2138         if (!map_open_params_to_ntcreate(fname, deny_mode,
2139                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
2140                                          &share_mode, &create_disposition,
2141                                          &create_options, &private_flags)) {
2142                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2143                 goto out;
2144         }
2145
2146         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2147
2148         status = filename_convert(ctx,
2149                                 conn,
2150                                 fname,
2151                                 ucf_flags,
2152                                 NULL,
2153                                 NULL,
2154                                 &smb_fname);
2155         if (!NT_STATUS_IS_OK(status)) {
2156                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2157                         reply_botherror(req,
2158                                         NT_STATUS_PATH_NOT_COVERED,
2159                                         ERRSRV, ERRbadpath);
2160                         goto out;
2161                 }
2162                 reply_nterror(req, status);
2163                 goto out;
2164         }
2165
2166         status = SMB_VFS_CREATE_FILE(
2167                 conn,                                   /* conn */
2168                 req,                                    /* req */
2169                 0,                                      /* root_dir_fid */
2170                 smb_fname,                              /* fname */
2171                 access_mask,                            /* access_mask */
2172                 share_mode,                             /* share_access */
2173                 create_disposition,                     /* create_disposition*/
2174                 create_options,                         /* create_options */
2175                 dos_attr,                               /* file_attributes */
2176                 oplock_request,                         /* oplock_request */
2177                 NULL,                                   /* lease */
2178                 0,                                      /* allocation_size */
2179                 private_flags,
2180                 NULL,                                   /* sd */
2181                 NULL,                                   /* ea_list */
2182                 &fsp,                                   /* result */
2183                 &info,                                  /* pinfo */
2184                 NULL, NULL);                            /* create context */
2185
2186         if (!NT_STATUS_IS_OK(status)) {
2187                 if (open_was_deferred(req->xconn, req->mid)) {
2188                         /* We have re-scheduled this call. */
2189                         goto out;
2190                 }
2191                 reply_openerror(req, status);
2192                 goto out;
2193         }
2194
2195         /* Ensure we're pointing at the correct stat struct. */
2196         TALLOC_FREE(smb_fname);
2197         smb_fname = fsp->fsp_name;
2198
2199         size = smb_fname->st.st_ex_size;
2200         fattr = dos_mode(conn, smb_fname);
2201
2202         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2203
2204         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2205                 DEBUG(3,("attempt to open a directory %s\n",
2206                          fsp_str_dbg(fsp)));
2207                 close_file(req, fsp, ERROR_CLOSE);
2208                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2209                         ERRDOS, ERRnoaccess);
2210                 goto out;
2211         }
2212
2213         reply_outbuf(req, 7, 0);
2214         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2215         SSVAL(req->outbuf,smb_vwv1,fattr);
2216         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2217                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2218         } else {
2219                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2220         }
2221         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2222         SSVAL(req->outbuf,smb_vwv6,deny_mode);
2223
2224         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2225                 SCVAL(req->outbuf,smb_flg,
2226                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2227         }
2228
2229         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2230                 SCVAL(req->outbuf,smb_flg,
2231                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2232         }
2233  out:
2234         END_PROFILE(SMBopen);
2235         return;
2236 }
2237
2238 /****************************************************************************
2239  Reply to an open and X.
2240 ****************************************************************************/
2241
2242 void reply_open_and_X(struct smb_request *req)
2243 {
2244         connection_struct *conn = req->conn;
2245         struct smb_filename *smb_fname = NULL;
2246         char *fname = NULL;
2247         uint16_t open_flags;
2248         int deny_mode;
2249         uint32_t smb_attr;
2250         /* Breakout the oplock request bits so we can set the
2251                 reply bits separately. */
2252         int ex_oplock_request;
2253         int core_oplock_request;
2254         int oplock_request;
2255 #if 0
2256         int smb_sattr = SVAL(req->vwv+4, 0);
2257         uint32_t smb_time = make_unix_date3(req->vwv+6);
2258 #endif
2259         int smb_ofun;
2260         uint32_t fattr=0;
2261         int mtime=0;
2262         int smb_action = 0;
2263         files_struct *fsp;
2264         NTSTATUS status;
2265         uint64_t allocation_size;
2266         ssize_t retval = -1;
2267         uint32_t access_mask;
2268         uint32_t share_mode;
2269         uint32_t create_disposition;
2270         uint32_t create_options = 0;
2271         uint32_t private_flags = 0;
2272         uint32_t ucf_flags;
2273         TALLOC_CTX *ctx = talloc_tos();
2274
2275         START_PROFILE(SMBopenX);
2276
2277         if (req->wct < 15) {
2278                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2279                 goto out;
2280         }
2281
2282         open_flags = SVAL(req->vwv+2, 0);
2283         deny_mode = SVAL(req->vwv+3, 0);
2284         smb_attr = SVAL(req->vwv+5, 0);
2285         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2286         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2287         oplock_request = ex_oplock_request | core_oplock_request;
2288         smb_ofun = SVAL(req->vwv+8, 0);
2289         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2290
2291         /* If it's an IPC, pass off the pipe handler. */
2292         if (IS_IPC(conn)) {
2293                 if (lp_nt_pipe_support()) {
2294                         reply_open_pipe_and_X(conn, req);
2295                 } else {
2296                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2297                 }
2298                 goto out;
2299         }
2300
2301         /* XXXX we need to handle passed times, sattr and flags */
2302         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2303                         STR_TERMINATE, &status);
2304         if (!NT_STATUS_IS_OK(status)) {
2305                 reply_nterror(req, status);
2306                 goto out;
2307         }
2308
2309         if (!map_open_params_to_ntcreate(fname, deny_mode,
2310                                          smb_ofun,
2311                                          &access_mask, &share_mode,
2312                                          &create_disposition,
2313                                          &create_options,
2314                                          &private_flags)) {
2315                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2316                 goto out;
2317         }
2318
2319         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2320
2321         status = filename_convert(ctx,
2322                                 conn,
2323                                 fname,
2324                                 ucf_flags,
2325                                 NULL,
2326                                 NULL,
2327                                 &smb_fname);
2328         if (!NT_STATUS_IS_OK(status)) {
2329                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2330                         reply_botherror(req,
2331                                         NT_STATUS_PATH_NOT_COVERED,
2332                                         ERRSRV, ERRbadpath);
2333                         goto out;
2334                 }
2335                 reply_nterror(req, status);
2336                 goto out;
2337         }
2338
2339         status = SMB_VFS_CREATE_FILE(
2340                 conn,                                   /* conn */
2341                 req,                                    /* req */
2342                 0,                                      /* root_dir_fid */
2343                 smb_fname,                              /* fname */
2344                 access_mask,                            /* access_mask */
2345                 share_mode,                             /* share_access */
2346                 create_disposition,                     /* create_disposition*/
2347                 create_options,                         /* create_options */
2348                 smb_attr,                               /* file_attributes */
2349                 oplock_request,                         /* oplock_request */
2350                 NULL,                                   /* lease */
2351                 0,                                      /* allocation_size */
2352                 private_flags,
2353                 NULL,                                   /* sd */
2354                 NULL,                                   /* ea_list */
2355                 &fsp,                                   /* result */
2356                 &smb_action,                            /* pinfo */
2357                 NULL, NULL);                            /* create context */
2358
2359         if (!NT_STATUS_IS_OK(status)) {
2360                 if (open_was_deferred(req->xconn, req->mid)) {
2361                         /* We have re-scheduled this call. */
2362                         goto out;
2363                 }
2364                 reply_openerror(req, status);
2365                 goto out;
2366         }
2367
2368         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2369            if the file is truncated or created. */
2370         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2371                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2372                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2373                         close_file(req, fsp, ERROR_CLOSE);
2374                         reply_nterror(req, NT_STATUS_DISK_FULL);
2375                         goto out;
2376                 }
2377                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2378                 if (retval < 0) {
2379                         close_file(req, fsp, ERROR_CLOSE);
2380                         reply_nterror(req, NT_STATUS_DISK_FULL);
2381                         goto out;
2382                 }
2383                 status = vfs_stat_fsp(fsp);
2384                 if (!NT_STATUS_IS_OK(status)) {
2385                         close_file(req, fsp, ERROR_CLOSE);
2386                         reply_nterror(req, status);
2387                         goto out;
2388                 }
2389         }
2390
2391         fattr = dos_mode(conn, fsp->fsp_name);
2392         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2393         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2394                 close_file(req, fsp, ERROR_CLOSE);
2395                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2396                 goto out;
2397         }
2398
2399         /* If the caller set the extended oplock request bit
2400                 and we granted one (by whatever means) - set the
2401                 correct bit for extended oplock reply.
2402         */
2403
2404         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2405                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2406         }
2407
2408         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2409                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2410         }
2411
2412         /* If the caller set the core oplock request bit
2413                 and we granted one (by whatever means) - set the
2414                 correct bit for core oplock reply.
2415         */
2416
2417         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2418                 reply_outbuf(req, 19, 0);
2419         } else {
2420                 reply_outbuf(req, 15, 0);
2421         }
2422
2423         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2424         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2425
2426         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2427                 SCVAL(req->outbuf, smb_flg,
2428                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2429         }
2430
2431         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2432                 SCVAL(req->outbuf, smb_flg,
2433                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2434         }
2435
2436         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2437         SSVAL(req->outbuf,smb_vwv3,fattr);
2438         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2439                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2440         } else {
2441                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2442         }
2443         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2444         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2445         SSVAL(req->outbuf,smb_vwv11,smb_action);
2446
2447         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2448                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2449         }
2450
2451  out:
2452         TALLOC_FREE(smb_fname);
2453         END_PROFILE(SMBopenX);
2454         return;
2455 }
2456
2457 /****************************************************************************
2458  Reply to a SMBulogoffX.
2459 ****************************************************************************/
2460
2461 void reply_ulogoffX(struct smb_request *req)
2462 {
2463         struct smbd_server_connection *sconn = req->sconn;
2464         struct user_struct *vuser;
2465         struct smbXsrv_session *session = NULL;
2466         NTSTATUS status;
2467
2468         START_PROFILE(SMBulogoffX);
2469
2470         vuser = get_valid_user_struct(sconn, req->vuid);
2471
2472         if(vuser == NULL) {
2473                 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2474                          (unsigned long long)req->vuid));
2475
2476                 req->vuid = UID_FIELD_INVALID;
2477                 reply_force_doserror(req, ERRSRV, ERRbaduid);
2478                 END_PROFILE(SMBulogoffX);
2479                 return;
2480         }
2481
2482         session = vuser->session;
2483         vuser = NULL;
2484
2485         /*
2486          * TODO: cancel all outstanding requests on the session
2487          */
2488         status = smbXsrv_session_logoff(session);
2489         if (!NT_STATUS_IS_OK(status)) {
2490                 DEBUG(0, ("reply_ulogoff: "
2491                           "smbXsrv_session_logoff() failed: %s\n",
2492                           nt_errstr(status)));
2493                 /*
2494                  * If we hit this case, there is something completely
2495                  * wrong, so we better disconnect the transport connection.
2496                  */
2497                 END_PROFILE(SMBulogoffX);
2498                 exit_server(__location__ ": smbXsrv_session_logoff failed");
2499                 return;
2500         }
2501
2502         TALLOC_FREE(session);
2503
2504         reply_outbuf(req, 2, 0);
2505         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2506         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2507
2508         DEBUG(3, ("ulogoffX vuid=%llu\n",
2509                   (unsigned long long)req->vuid));
2510
2511         END_PROFILE(SMBulogoffX);
2512         req->vuid = UID_FIELD_INVALID;
2513 }
2514
2515 /****************************************************************************
2516  Reply to a mknew or a create.
2517 ****************************************************************************/
2518
2519 void reply_mknew(struct smb_request *req)
2520 {
2521         connection_struct *conn = req->conn;
2522         struct smb_filename *smb_fname = NULL;
2523         char *fname = NULL;
2524         uint32_t fattr = 0;
2525         struct smb_file_time ft;
2526         files_struct *fsp;
2527         int oplock_request = 0;
2528         NTSTATUS status;
2529         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2530         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2531         uint32_t create_disposition;
2532         uint32_t create_options = 0;
2533         uint32_t ucf_flags;
2534         TALLOC_CTX *ctx = talloc_tos();
2535
2536         START_PROFILE(SMBcreate);
2537         ZERO_STRUCT(ft);
2538
2539         if (req->wct < 3) {
2540                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2541                 goto out;
2542         }
2543
2544         fattr = SVAL(req->vwv+0, 0);
2545         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2546
2547         if (req->cmd == SMBmknew) {
2548                 /* We should fail if file exists. */
2549                 create_disposition = FILE_CREATE;
2550         } else {
2551                 /* Create if file doesn't exist, truncate if it does. */
2552                 create_disposition = FILE_OVERWRITE_IF;
2553         }
2554
2555         /* mtime. */
2556         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2557
2558         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2559                             STR_TERMINATE, &status);
2560         if (!NT_STATUS_IS_OK(status)) {
2561                 reply_nterror(req, status);
2562                 goto out;
2563         }
2564
2565         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2566         status = filename_convert(ctx,
2567                                 conn,
2568                                 fname,
2569                                 ucf_flags,
2570                                 NULL,
2571                                 NULL,
2572                                 &smb_fname);
2573         if (!NT_STATUS_IS_OK(status)) {
2574                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2575                         reply_botherror(req,
2576                                         NT_STATUS_PATH_NOT_COVERED,
2577                                         ERRSRV, ERRbadpath);
2578                         goto out;
2579                 }
2580                 reply_nterror(req, status);
2581                 goto out;
2582         }
2583
2584         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2585                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2586                          "please report this\n",
2587                          smb_fname_str_dbg(smb_fname)));
2588         }
2589
2590         status = SMB_VFS_CREATE_FILE(
2591                 conn,                                   /* conn */
2592                 req,                                    /* req */
2593                 0,                                      /* root_dir_fid */
2594                 smb_fname,                              /* fname */
2595                 access_mask,                            /* access_mask */
2596                 share_mode,                             /* share_access */
2597                 create_disposition,                     /* create_disposition*/
2598                 create_options,                         /* create_options */
2599                 fattr,                                  /* file_attributes */
2600                 oplock_request,                         /* oplock_request */
2601                 NULL,                                   /* lease */
2602                 0,                                      /* allocation_size */
2603                 0,                                      /* private_flags */
2604                 NULL,                                   /* sd */
2605                 NULL,                                   /* ea_list */
2606                 &fsp,                                   /* result */
2607                 NULL,                                   /* pinfo */
2608                 NULL, NULL);                            /* create context */
2609
2610         if (!NT_STATUS_IS_OK(status)) {
2611                 if (open_was_deferred(req->xconn, req->mid)) {
2612                         /* We have re-scheduled this call. */
2613                         goto out;
2614                 }
2615                 reply_openerror(req, status);
2616                 goto out;
2617         }
2618
2619         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2620         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2621         if (!NT_STATUS_IS_OK(status)) {
2622                 END_PROFILE(SMBcreate);
2623                 goto out;
2624         }
2625
2626         reply_outbuf(req, 1, 0);
2627         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2628
2629         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2630                 SCVAL(req->outbuf,smb_flg,
2631                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2632         }
2633
2634         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2635                 SCVAL(req->outbuf,smb_flg,
2636                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2637         }
2638
2639         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2640         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2641                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2642                   (unsigned int)fattr));
2643
2644  out:
2645         TALLOC_FREE(smb_fname);
2646         END_PROFILE(SMBcreate);
2647         return;
2648 }
2649
2650 /****************************************************************************
2651  Reply to a create temporary file.
2652 ****************************************************************************/
2653
2654 void reply_ctemp(struct smb_request *req)
2655 {
2656         connection_struct *conn = req->conn;
2657         struct smb_filename *smb_fname = NULL;
2658         char *wire_name = NULL;
2659         char *fname = NULL;
2660         uint32_t fattr;
2661         files_struct *fsp;
2662         int oplock_request;
2663         char *s;
2664         NTSTATUS status;
2665         int i;
2666         uint32_t ucf_flags;
2667         TALLOC_CTX *ctx = talloc_tos();
2668
2669         START_PROFILE(SMBctemp);
2670
2671         if (req->wct < 3) {
2672                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2673                 goto out;
2674         }
2675
2676         fattr = SVAL(req->vwv+0, 0);
2677         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2678
2679         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2680                             STR_TERMINATE, &status);
2681         if (!NT_STATUS_IS_OK(status)) {
2682                 reply_nterror(req, status);
2683                 goto out;
2684         }
2685
2686         for (i = 0; i < 10; i++) {
2687                 if (*wire_name) {
2688                         fname = talloc_asprintf(ctx,
2689                                         "%s/TMP%s",
2690                                         wire_name,
2691                                         generate_random_str_list(ctx, 5, "0123456789"));
2692                 } else {
2693                         fname = talloc_asprintf(ctx,
2694                                         "TMP%s",
2695                                         generate_random_str_list(ctx, 5, "0123456789"));
2696                 }
2697
2698                 if (!fname) {
2699                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2700                         goto out;
2701                 }
2702
2703                 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2704                 status = filename_convert(ctx, conn,
2705                                 fname,
2706                                 ucf_flags,
2707                                 NULL,
2708                                 NULL,
2709                                 &smb_fname);
2710                 if (!NT_STATUS_IS_OK(status)) {
2711                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2712                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2713                                         ERRSRV, ERRbadpath);
2714                                 goto out;
2715                         }
2716                         reply_nterror(req, status);
2717                         goto out;
2718                 }
2719
2720                 /* Create the file. */
2721                 status = SMB_VFS_CREATE_FILE(
2722                         conn,                                   /* conn */
2723                         req,                                    /* req */
2724                         0,                                      /* root_dir_fid */
2725                         smb_fname,                              /* fname */
2726                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2727                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2728                         FILE_CREATE,                            /* create_disposition*/
2729                         0,                                      /* create_options */
2730                         fattr,                                  /* file_attributes */
2731                         oplock_request,                         /* oplock_request */
2732                         NULL,                                   /* lease */
2733                         0,                                      /* allocation_size */
2734                         0,                                      /* private_flags */
2735                         NULL,                                   /* sd */
2736                         NULL,                                   /* ea_list */
2737                         &fsp,                                   /* result */
2738                         NULL,                                   /* pinfo */
2739                         NULL, NULL);                            /* create context */
2740
2741                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2742                         TALLOC_FREE(fname);
2743                         TALLOC_FREE(smb_fname);
2744                         continue;
2745                 }
2746
2747                 if (!NT_STATUS_IS_OK(status)) {
2748                         if (open_was_deferred(req->xconn, req->mid)) {
2749                                 /* We have re-scheduled this call. */
2750                                 goto out;
2751                         }
2752                         reply_openerror(req, status);
2753                         goto out;
2754                 }
2755
2756                 break;
2757         }
2758
2759         if (i == 10) {
2760                 /* Collision after 10 times... */
2761                 reply_nterror(req, status);
2762                 goto out;
2763         }
2764
2765         reply_outbuf(req, 1, 0);
2766         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2767
2768         /* the returned filename is relative to the directory */
2769         s = strrchr_m(fsp->fsp_name->base_name, '/');
2770         if (!s) {
2771                 s = fsp->fsp_name->base_name;
2772         } else {
2773                 s++;
2774         }
2775
2776 #if 0
2777         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2778            thing in the byte section. JRA */
2779         SSVALS(p, 0, -1); /* what is this? not in spec */
2780 #endif
2781         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2782             == -1) {
2783                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2784                 goto out;
2785         }
2786
2787         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2788                 SCVAL(req->outbuf, smb_flg,
2789                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2790         }
2791
2792         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2793                 SCVAL(req->outbuf, smb_flg,
2794                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2795         }
2796
2797         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2798         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2799                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2800  out:
2801         TALLOC_FREE(smb_fname);
2802         TALLOC_FREE(wire_name);
2803         END_PROFILE(SMBctemp);
2804         return;
2805 }
2806
2807 /*******************************************************************
2808  Check if a user is allowed to rename a file.
2809 ********************************************************************/
2810
2811 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2812                         uint16_t dirtype)
2813 {
2814         if (!CAN_WRITE(conn)) {
2815                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2816         }
2817
2818         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2819                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2820                 /* Only bother to read the DOS attribute if we might deny the
2821                    rename on the grounds of attribute mismatch. */
2822                 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2823                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2824                         return NT_STATUS_NO_SUCH_FILE;
2825                 }
2826         }
2827
2828         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2829                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2830                         return NT_STATUS_OK;
2831                 }
2832
2833                 /* If no pathnames are open below this
2834                    directory, allow the rename. */
2835
2836                 if (lp_strict_rename(SNUM(conn))) {
2837                         /*
2838                          * Strict rename, check open file db.
2839                          */
2840                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2841                                 return NT_STATUS_ACCESS_DENIED;
2842                         }
2843                 } else if (file_find_subpath(fsp)) {
2844                         /*
2845                          * No strict rename, just look in local process.
2846                          */
2847                         return NT_STATUS_ACCESS_DENIED;
2848                 }
2849                 return NT_STATUS_OK;
2850         }
2851
2852         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2853                 return NT_STATUS_OK;
2854         }
2855
2856         return NT_STATUS_ACCESS_DENIED;
2857 }
2858
2859 /*******************************************************************
2860  * unlink a file with all relevant access checks
2861  *******************************************************************/
2862
2863 static NTSTATUS do_unlink(connection_struct *conn,
2864                         struct smb_request *req,
2865                         struct smb_filename *smb_fname,
2866                         uint32_t dirtype)
2867 {
2868         uint32_t fattr;
2869         files_struct *fsp;
2870         uint32_t dirtype_orig = dirtype;
2871         NTSTATUS status;
2872         int ret;
2873         bool posix_paths = (req != NULL && req->posix_pathnames);
2874
2875         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2876                   smb_fname_str_dbg(smb_fname),
2877                   dirtype));
2878
2879         if (!CAN_WRITE(conn)) {
2880                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2881         }
2882
2883         if (posix_paths) {
2884                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2885         } else {
2886                 ret = SMB_VFS_STAT(conn, smb_fname);
2887         }
2888         if (ret != 0) {
2889                 return map_nt_error_from_unix(errno);
2890         }
2891
2892         fattr = dos_mode(conn, smb_fname);
2893
2894         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2895                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2896         }
2897
2898         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2899         if (!dirtype) {
2900                 return NT_STATUS_NO_SUCH_FILE;
2901         }
2902
2903         if (!dir_check_ftype(fattr, dirtype)) {
2904                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2905                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2906                 }
2907                 return NT_STATUS_NO_SUCH_FILE;
2908         }
2909
2910         if (dirtype_orig & 0x8000) {
2911                 /* These will never be set for POSIX. */
2912                 return NT_STATUS_NO_SUCH_FILE;
2913         }
2914
2915 #if 0
2916         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2917                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2918         }
2919
2920         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2921                 return NT_STATUS_NO_SUCH_FILE;
2922         }
2923
2924         if (dirtype & 0xFF00) {
2925                 /* These will never be set for POSIX. */
2926                 return NT_STATUS_NO_SUCH_FILE;
2927         }
2928
2929         dirtype &= 0xFF;
2930         if (!dirtype) {
2931                 return NT_STATUS_NO_SUCH_FILE;
2932         }
2933
2934         /* Can't delete a directory. */
2935         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2936                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2937         }
2938 #endif
2939
2940 #if 0 /* JRATEST */
2941         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2942                 return NT_STATUS_OBJECT_NAME_INVALID;
2943 #endif /* JRATEST */
2944
2945         /* On open checks the open itself will check the share mode, so
2946            don't do it here as we'll get it wrong. */
2947
2948         status = SMB_VFS_CREATE_FILE
2949                 (conn,                  /* conn */
2950                  req,                   /* req */
2951                  0,                     /* root_dir_fid */
2952                  smb_fname,             /* fname */
2953                  DELETE_ACCESS,         /* access_mask */
2954                  FILE_SHARE_NONE,       /* share_access */
2955                  FILE_OPEN,             /* create_disposition*/
2956                  FILE_NON_DIRECTORY_FILE, /* create_options */
2957                                         /* file_attributes */
2958                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2959                                 FILE_ATTRIBUTE_NORMAL,
2960                  0,                     /* oplock_request */
2961                  NULL,                  /* lease */
2962                  0,                     /* allocation_size */