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