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