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